ilustrace SEO v Next.js 15

SEO průvodce pro Next.js 15

Ahoj! Vítejte u našeho podrobného SEO průvodce pro Next.js 15. V tomto článku si krok za krokem projdeme všechno od nastavení nového Metadata API přes pokročilé techniky až po monitorování výkonu a metrik. Vše vysvětlíme přátelským jazykem a ukážeme si konkrétní kódy, které jen zkopírujete do svého projektu. Pojďme na to!

Příprava projektu a Metadata API

Nejprve se ujistěte, že máte ve svém projektu složku /app. V ní vytvořte soubor /app/layout.tsx a definujte globální metadata. Next.js 15 přináší vylepšené Metadata API, které vám umožní centralizovat veškeré SEO nastavení na jednom místě.

// /app/layout.tsx
import { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Kompletní SEO průvodce pro Next.js 15',
  description: 'Rozsáhlý návod na SEO v Next.js 15: od metadat až po monitoring',
  metadataBase: new URL(process.env.NEXT_PUBLIC_BASE_URL || 'https://webzi.cz'),
  alternates: {
    canonical: '/blog/seo-optimalizace-nextjs-15',
    languages: {
      cs: '/cs/blog/seo-optimalizace-nextjs-15',
      en: '/en/blog/seo-optimalizace-nextjs-15'
    }
  },
  openGraph: {
    title: 'SEO Next.js 15',
    description: 'Jak optimalizovat SEO v Next.js 15',
    url: '/blog/seo-optimalizace-nextjs-15',
    images: ['/assets/img/blog/seo-nextjs15-hero.jpg']
  },
  twitter: { card: 'summary_large_image' },
  other: {
    robots: 'index, follow'
  }
};

Použitím metadataBase získáte flexibilitu mezi stagingem a produkcí díky env proměnné NEXT_PUBLIC_BASE_URL. Sekce alternates automaticky vygeneruje hreflang tagy pro vícejazyčné verze.

Vlastní hlavička pro speciální tagy

Pro meta tagy, které Metadata API standardně nepokrývá (např. viewport nebo přednahrávání fontů), vytvořte komponentu app/head.tsx s funkcí Head, která vrací čisté HTML.

// /app/head.tsx
'use client';
import React from 'react';

export default function Head() {
  return (
    <>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      {/* Přidejte další custom tagy, např. preconnect pro fonty */}
      <link rel="preconnect" href="https://fonts.googleapis.com" />
    </>
  );
}

Díky této komponentě zajistíte, že máte plnou kontrolu nad každým meta tagem, aniž byste přišli o výhody server-side renderingu.

Open Graph a Twitter Cards

Pro atraktivní náhledy na sociálních sítích využijte sekce openGraph a twitter v metadata. Next.js se postará o generování všech potřebných <meta> tagů.

Strukturovaná data pomocí JSON-LD

Rich snippets (hvězdičky, autor, datum) získáte vložením JSON-LD do hlavičky pomocí dangerouslySetInnerHTML. Níže je příklad objektu BlogPosting podle schema.org.

// /app/layout.tsx (pokračování)

const jsonLd = {
  '@context': 'https://schema.org',
  '@type': 'BlogPosting',
  headline: metadata.title,
  image: [new URL(metadata.openGraph.images[0], metadata.metadataBase).toString()],
  author: { '@type': 'Person', name: metadata.author || 'Webzi Team' },
  publisher: {
    '@type': 'Organization',
    name: 'Webzi',
    logo: { '@type': 'ImageObject', url: 'https://webzi.cz/assets/img/logo/meta_webzi_logo.png' }
  },
  datePublished: '2025-05-19'
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="cs">
      <head>
        {/* metadata se generuje automaticky */}
        <script
          type="application/ld+json"
          dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

Generování sitemapy

Dynamická sitemap pomáhá vyhledávačům rychle najít nové stránky. Vytvořte route handler v app/api/sitemap/route.ts a použijte env proměnnou NEXT_PUBLIC_BASE_URL pro základní URL.

// /app/api/sitemap/route.ts
import { NextResponse } from 'next/server';
import dbConnect from '@/app/src/lib/mongoose';
import BlogPost from '@/app/src/lib/models/BlogPost';
const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || 'https://webzi.cz';

export async function GET() {
  await dbConnect();
  const posts = await BlogPost.find().lean();
  const urls = posts
    .map(
      (p) =>
        `<url><loc>${BASE_URL}/blog/${p.slug}</loc><changefreq>weekly</changefreq></url>`
    )
    .join('');
  const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${urls}</urlset>`;
  return new NextResponse(xml, { headers: { 'Content-Type': 'application/xml' } });
}

Crawl optimalizace

Soubor robots.txt umístěte do /public/robots.txt. Zablokujte nepotřebné cesty a odkažte na sitemapu. Příklad:

User-agent: *
Disallow: /api/private
Allow: /blog
Sitemap: https://webzi.cz/api/sitemap

Optimalizace obrázků a Core Web Vitals

Next.js 15 doporučuje stabilní komponentu next/image pro lazy-loading, responsive sizing a WebP/AVIF. Sledujte metriky LCP, FID a CLS pomocí nástrojů jako Lighthouse.

import Image from 'next/image';

export default function Hero() {
  return (
    <Image
      src="/assets/img/blog/seo-nextjs15-hero.jpg"
      alt="SEO Next.js 15"
      width={1200}
      height={630}
      priority
    />
  );
}

Internationalizace a hreflang

Díky sekci alternates.languages v metadata Next.js automaticky přidá tagy hreflang. Pro další jazyky doplňte objekt languages.

Přístupnost a semantika

Používejte správné HTML elementy (h1h6, nav, main, article) a vždy přidávejte alt atributy k obrázkům. Tím zajistíte lepší UX i indexaci asistivními technologiemi.

Interní prolinkování

Komponenta Link z next/link pomáhá s prefetch a rychlou navigací. Budujte logickou URL strukturu, aby příbuzné články byly snadno dohledatelné.

Monitoring SEO, analytika a alerty

Integrujte Google Analytics 4 a Search Console API. Vložte do aplikace komponentu next/script s atributem strategy="afterInteractive" a nastavte upozornění na nečekaný pokles návštěvnosti.

import Script from 'next/script';

export default function Analytics() {
  return (
    <>
      <Script
        src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA4_ID}`}
        strategy="afterInteractive"
      />
      <Script id="ga4-config" strategy="afterInteractive">
        {`window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);} 
gtag('js', new Date());
gtag('config', '${process.env.NEXT_PUBLIC_GA4_ID}');`}
      </Script>
    </>
  );
}

SDÍLET:

Komentáře (0)

Načítám komentáře...

Přidat komentář

Váš email nebude zveřejněn. Všechny komentáře procházejí schválením administrátorem.