mirror of
https://gitlab.com/foxixus/neomovies.git
synced 2025-10-27 17:38:50 +05:00
Improve SEO
This commit is contained in:
8
next-sitemap.config.js
Normal file
8
next-sitemap.config.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/** @type {import('next-sitemap').IConfig} */
|
||||||
|
module.exports = {
|
||||||
|
siteUrl: 'https://neomovies.ru',
|
||||||
|
generateRobotsTxt: true, // создает robots.txt
|
||||||
|
sitemapSize: 7000,
|
||||||
|
// игнорируем служебные пути
|
||||||
|
exclude: ['/admin', '/auth'],
|
||||||
|
};
|
||||||
@@ -5,10 +5,12 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev --turbopack",
|
"dev": "next dev --turbopack",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
|
"postbuild": "next-sitemap",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"@reduxjs/toolkit": "^2.5.0",
|
"@reduxjs/toolkit": "^2.5.0",
|
||||||
"@tabler/icons-react": "^3.26.0",
|
"@tabler/icons-react": "^3.26.0",
|
||||||
"@types/bcrypt": "^5.0.2",
|
"@types/bcrypt": "^5.0.2",
|
||||||
@@ -21,7 +23,9 @@
|
|||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
"framer-motion": "^11.15.0",
|
"framer-motion": "^11.15.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -29,6 +33,7 @@
|
|||||||
"mongodb": "^6.12.0",
|
"mongodb": "^6.12.0",
|
||||||
"mongoose": "^8.9.2",
|
"mongoose": "^8.9.2",
|
||||||
"next": "15.1.2",
|
"next": "15.1.2",
|
||||||
|
"next-seo": "^6.8.0",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"nodemailer": "^6.9.16",
|
"nodemailer": "^6.9.16",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
@@ -38,7 +43,8 @@
|
|||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"resend": "^4.0.1",
|
"resend": "^4.0.1",
|
||||||
"styled-components": "^6.1.13",
|
"styled-components": "^6.1.13",
|
||||||
"tailwind": "^4.0.0"
|
"tailwind": "^4.0.0",
|
||||||
|
"tailwind-merge": "^3.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
@@ -47,6 +53,7 @@
|
|||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "15.1.2",
|
"eslint-config-next": "15.1.2",
|
||||||
|
"next-sitemap": "^4.2.3",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
|
|||||||
21
public/manifest.json
Normal file
21
public/manifest.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "NeoMovies",
|
||||||
|
"short_name": "NeoMovies",
|
||||||
|
"start_url": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"background_color": "#000000",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"description": "Смотрите фильмы и сериалы онлайн на NeoMovies.",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/public/logo.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/public/logo.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Inter } from 'next/font/google';
|
import { Inter } from 'next/font/google';
|
||||||
import Script from 'next/script';
|
import Script from 'next/script';
|
||||||
import './globals.css';
|
import './globals.css';
|
||||||
|
import { DefaultSeo } from 'next-seo';
|
||||||
|
import SEO from '@/next-seo.config';
|
||||||
import { ClientLayout } from '@/components/ClientLayout';
|
import { ClientLayout } from '@/components/ClientLayout';
|
||||||
import { Providers } from '@/components/Providers';
|
import { Providers } from '@/components/Providers';
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
@@ -23,6 +25,9 @@ export default function RootLayout({
|
|||||||
<html lang="ru">
|
<html lang="ru">
|
||||||
<head>
|
<head>
|
||||||
<meta name="darkreader-lock" />
|
<meta name="darkreader-lock" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/public/logo.png" />
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
|
||||||
{/* Google tag (gtag.js) */}
|
{/* Google tag (gtag.js) */}
|
||||||
<Script
|
<Script
|
||||||
@@ -61,6 +66,7 @@ export default function RootLayout({
|
|||||||
></iframe>
|
></iframe>
|
||||||
</noscript>
|
</noscript>
|
||||||
{/* End Google Tag Manager (noscript) */}
|
{/* End Google Tag Manager (noscript) */}
|
||||||
|
<DefaultSeo {...SEO} />
|
||||||
<Providers>
|
<Providers>
|
||||||
<ClientLayout>{children}</ClientLayout>
|
<ClientLayout>{children}</ClientLayout>
|
||||||
</Providers>
|
</Providers>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import FavoriteButton from '@/components/FavoriteButton';
|
|||||||
import Reactions from '@/components/Reactions';
|
import Reactions from '@/components/Reactions';
|
||||||
import { formatDate } from '@/lib/utils';
|
import { formatDate } from '@/lib/utils';
|
||||||
import { PlayCircle, ArrowLeft } from 'lucide-react';
|
import { PlayCircle, ArrowLeft } from 'lucide-react';
|
||||||
|
import { NextSeo } from 'next-seo';
|
||||||
|
|
||||||
interface MovieContentProps {
|
interface MovieContentProps {
|
||||||
movieId: string;
|
movieId: string;
|
||||||
@@ -62,6 +63,39 @@ export default function MovieContent({ movieId, initialMovie }: MovieContentProp
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<NextSeo
|
||||||
|
title={`${movie.title} смотреть онлайн`}
|
||||||
|
description={movie.overview?.slice(0, 150)}
|
||||||
|
canonical={`https://neomovies.ru/movie/${movie.id}`}
|
||||||
|
openGraph={{
|
||||||
|
url: `https://neomovies.ru/movie/${movie.id}`,
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: getImageUrl(movie.poster_path, 'w780'),
|
||||||
|
alt: movie.title,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* schema.org Movie */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: JSON.stringify({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Movie',
|
||||||
|
name: movie.title,
|
||||||
|
image: getImageUrl(movie.poster_path, 'w780'),
|
||||||
|
description: movie.overview,
|
||||||
|
datePublished: movie.release_date,
|
||||||
|
aggregateRating: {
|
||||||
|
'@type': 'AggregateRating',
|
||||||
|
ratingValue: movie.vote_average,
|
||||||
|
ratingCount: movie.vote_count,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<div className="min-h-screen bg-background text-foreground px-4 py-6 md:px-6 lg:px-8">
|
<div className="min-h-screen bg-background text-foreground px-4 py-6 md:px-6 lg:px-8">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="grid grid-cols-1 gap-8 md:grid-cols-3">
|
<div className="grid grid-cols-1 gap-8 md:grid-cols-3">
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import FavoriteButton from '@/components/FavoriteButton';
|
|||||||
import Reactions from '@/components/Reactions';
|
import Reactions from '@/components/Reactions';
|
||||||
import { formatDate } from '@/lib/utils';
|
import { formatDate } from '@/lib/utils';
|
||||||
import { PlayCircle, ArrowLeft } from 'lucide-react';
|
import { PlayCircle, ArrowLeft } from 'lucide-react';
|
||||||
|
import { NextSeo } from 'next-seo';
|
||||||
|
|
||||||
interface TVContentProps {
|
interface TVContentProps {
|
||||||
showId: string;
|
showId: string;
|
||||||
@@ -69,6 +70,39 @@ export default function TVContent({ showId, initialShow }: TVContentProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<NextSeo
|
||||||
|
title={`${show.name} смотреть онлайн`}
|
||||||
|
description={show.overview?.slice(0, 150)}
|
||||||
|
canonical={`https://neomovies.ru/tv/${show.id}`}
|
||||||
|
openGraph={{
|
||||||
|
url: `https://neomovies.ru/tv/${show.id}`,
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: getImageUrl(show.poster_path, 'w780'),
|
||||||
|
alt: show.name,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/* schema.org TVSeries */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: JSON.stringify({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TVSeries',
|
||||||
|
name: show.name,
|
||||||
|
image: getImageUrl(show.poster_path, 'w780'),
|
||||||
|
description: show.overview,
|
||||||
|
numberOfSeasons: show.number_of_seasons,
|
||||||
|
aggregateRating: {
|
||||||
|
'@type': 'AggregateRating',
|
||||||
|
ratingValue: show.vote_average,
|
||||||
|
ratingCount: show.vote_count,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<div className="min-h-screen bg-background text-foreground px-4 py-6 md:px-6 lg:px-8">
|
<div className="min-h-screen bg-background text-foreground px-4 py-6 md:px-6 lg:px-8">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="grid grid-cols-1 gap-8 md:grid-cols-3">
|
<div className="grid grid-cols-1 gap-8 md:grid-cols-3">
|
||||||
|
|||||||
18
src/next-seo.config.ts
Normal file
18
src/next-seo.config.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
const SEO = {
|
||||||
|
titleTemplate: "%s | NeoMovies",
|
||||||
|
defaultTitle: "NeoMovies – смотреть фильмы и сериалы онлайн",
|
||||||
|
description:
|
||||||
|
"Смотрите фильмы и сериалы в хорошем качестве без регистрации – NeoMovies.",
|
||||||
|
canonical: "https://neomovies.ru",
|
||||||
|
openGraph: {
|
||||||
|
type: "website",
|
||||||
|
locale: "ru_RU",
|
||||||
|
url: "https://neomovies.ru",
|
||||||
|
siteName: "NeoMovies",
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
cardType: "summary_large_image",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SEO;
|
||||||
Reference in New Issue
Block a user