mirror of
https://github.com/JustAnimeCore/JustAnime.git
synced 2026-04-17 13:51:44 +00:00
.fun
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://justanime.to">
|
<a href="https://justanime.fun">
|
||||||
<img alt="JustAnime" src="https://github.com/tejaspanchall/JustAnime/blob/main/public/footer.png" width="220"/>
|
<img alt="JustAnime" src="https://github.com/tejaspanchall/JustAnime/blob/main/public/footer.png" width="220"/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://justanime.to">JustAnime</a> is an open-source anime streaming service that uses <a href="https://github.com/itzzzme/anime-api">ANIME</a> API, built using ReactJS with javascript and Tailwind CSS. It lets you easily find any anime with intuitive search & suggestion feature and stream without any ads.
|
<a href="https://justanime.fun">JustAnime</a> is an open-source anime streaming service that uses <a href="https://github.com/itzzzme/anime-api">ANIME</a> API, built using ReactJS with javascript and Tailwind CSS. It lets you easily find any anime with intuitive search & suggestion feature and stream without any ads.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -92,13 +92,13 @@ npm start # or npm run dev (to run develepment server)
|
|||||||
|
|
||||||
### Vercel
|
### Vercel
|
||||||
|
|
||||||
Host your own instance of <a href="https://justanime.to">JustAnime</a> on vercel
|
Host your own instance of <a href="https://justanime.fun">JustAnime</a> on vercel
|
||||||
|
|
||||||
[](https://vercel.com/new/clone?repository-url=https://github.com/tejaspanchall/JustAnime)
|
[](https://vercel.com/new/clone?repository-url=https://github.com/tejaspanchall/JustAnime)
|
||||||
|
|
||||||
### Render
|
### Render
|
||||||
|
|
||||||
Host your own instance of <a href="https://justanime.to">JustAnime</a> on Render.
|
Host your own instance of <a href="https://justanime.fun">JustAnime</a> on Render.
|
||||||
|
|
||||||
[](https://render.com/deploy?repo=https://github.com/tejaspanchall/JustAnime)
|
[](https://render.com/deploy?repo=https://github.com/tejaspanchall/JustAnime)
|
||||||
|
|
||||||
|
|||||||
14
index.html
14
index.html
@@ -40,7 +40,7 @@
|
|||||||
content="JustAnime to is a free no ads anime site to watch free anime. Online anime streaming at justanime with DUB, SUB in HD. Hianime, 9animetv, Zoro, s3taku,justanime."
|
content="JustAnime to is a free no ads anime site to watch free anime. Online anime streaming at justanime with DUB, SUB in HD. Hianime, 9animetv, Zoro, s3taku,justanime."
|
||||||
/>
|
/>
|
||||||
<meta property="og:image" content="https://i.postimg.cc/kMYmHkPm/home.webp" />
|
<meta property="og:image" content="https://i.postimg.cc/kMYmHkPm/home.webp" />
|
||||||
<meta property="og:url" content="https://justanime.to" />
|
<meta property="og:url" content="https://justanime.fun" />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:locale" content="en_US" />
|
<meta property="og:locale" content="en_US" />
|
||||||
<meta property="og:site_name" content="JustAnime" />
|
<meta property="og:site_name" content="JustAnime" />
|
||||||
@@ -61,24 +61,24 @@
|
|||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "WebSite",
|
"@type": "WebSite",
|
||||||
"name": "JustAnime",
|
"name": "JustAnime",
|
||||||
"alternateName": ["JustAnime.to", "Just Anime"],
|
"alternateName": ["justanime.fun", "Just Anime"],
|
||||||
"url": "https://justanime.to",
|
"url": "https://justanime.fun",
|
||||||
"description": "JustAnime offers free streaming of English-subbed and dubbed anime series and movies. No account needed and no ads!",
|
"description": "JustAnime offers free streaming of English-subbed and dubbed anime series and movies. No account needed and no ads!",
|
||||||
"potentialAction": {
|
"potentialAction": {
|
||||||
"@type": "SearchAction",
|
"@type": "SearchAction",
|
||||||
"target": {
|
"target": {
|
||||||
"@type": "EntryPoint",
|
"@type": "EntryPoint",
|
||||||
"urlTemplate": "https://justanime.to/search?keyword={search_term_string}"
|
"urlTemplate": "https://justanime.fun/search?keyword={search_term_string}"
|
||||||
},
|
},
|
||||||
"query-input": "required name=search_term_string"
|
"query-input": "required name=search_term_string"
|
||||||
},
|
},
|
||||||
"publisher": {
|
"publisher": {
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
"name": "JustAnime",
|
"name": "JustAnime",
|
||||||
"url": "https://justanime.to",
|
"url": "https://justanime.fun",
|
||||||
"logo": {
|
"logo": {
|
||||||
"@type": "ImageObject",
|
"@type": "ImageObject",
|
||||||
"url": "https://justanime.to/logo.png",
|
"url": "https://justanime.fun/logo.png",
|
||||||
"width": 512,
|
"width": 512,
|
||||||
"height": 512
|
"height": 512
|
||||||
},
|
},
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<link rel="canonical" href="https://justanime.to" />
|
<link rel="canonical" href="https://justanime.fun" />
|
||||||
|
|
||||||
<!-- Preload Critical Resources -->
|
<!-- Preload Critical Resources -->
|
||||||
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
|
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ function Home() {
|
|||||||
<title>{website_name} | Free Anime Streaming Platform</title>
|
<title>{website_name} | Free Anime Streaming Platform</title>
|
||||||
<meta name="description" content={`${website_name} is the best site to watch anime online for free. Stream thousands of English subbed and dubbed anime episodes in HD quality with no ads.`} />
|
<meta name="description" content={`${website_name} is the best site to watch anime online for free. Stream thousands of English subbed and dubbed anime episodes in HD quality with no ads.`} />
|
||||||
<meta name="keywords" content="justanime, watch anime free, anime online sub dub, free anime streaming, no ads anime, best anime site" />
|
<meta name="keywords" content="justanime, watch anime free, anime online sub dub, free anime streaming, no ads anime, best anime site" />
|
||||||
<link rel="canonical" href="https://justanime.to" />
|
<link rel="canonical" href="https://justanime.fun" />
|
||||||
|
|
||||||
<meta property="og:title" content={`${website_name} | Free Anime Streaming Platform`} />
|
<meta property="og:title" content={`${website_name} | Free Anime Streaming Platform`} />
|
||||||
<meta property="og:description" content={`Watch high-quality anime online for free on ${website_name}. No ads, daily updates, and a massive library of subbed and dubbed content.`} />
|
<meta property="og:description" content={`Watch high-quality anime online for free on ${website_name}. No ads, daily updates, and a massive library of subbed and dubbed content.`} />
|
||||||
<meta property="og:url" content="https://justanime.to" />
|
<meta property="og:url" content="https://justanime.fun" />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ function DMCA() {
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p className="leading-relaxed text-base">
|
<p className="leading-relaxed text-base">
|
||||||
We take the intellectual property rights of others seriously and require that our Users do the same.
|
We take the intellectual property rights of others seriously and require that our Users do the same.
|
||||||
The Digital Millennium Copyright Act (DMCA) established a process for addressing claims of copyright infringement.
|
The Digital Millennium Copyright Act (DMCA) established a process for addressing claims of copyright infringement.
|
||||||
If you own a copyright or have authority to act on behalf of a copyright owner and want to report a claim that a
|
If you own a copyright or have authority to act on behalf of a copyright owner and want to report a claim that a
|
||||||
third party is infringing that material on or through {website_name}'s services, please submit a DMCA report on
|
third party is infringing that material on or through {website_name}'s services, please submit a DMCA report on
|
||||||
our Contact page, and we will take appropriate action.
|
our Contact page, and we will take appropriate action.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -47,11 +47,11 @@ function DMCA() {
|
|||||||
<h2 className="text-xl font-semibold text-white mb-4">Submit Your Request</h2>
|
<h2 className="text-xl font-semibold text-white mb-4">Submit Your Request</h2>
|
||||||
<p className="leading-relaxed text-base">
|
<p className="leading-relaxed text-base">
|
||||||
Your DMCA takedown request should be submit here:{' '}
|
Your DMCA takedown request should be submit here:{' '}
|
||||||
<a
|
<a
|
||||||
href="/contact"
|
href="/contact"
|
||||||
className="text-white hover:text-white/80 underline underline-offset-4 decoration-white/20 hover:decoration-white/40 transition-colors"
|
className="text-white hover:text-white/80 underline underline-offset-4 decoration-white/20 hover:decoration-white/40 transition-colors"
|
||||||
>
|
>
|
||||||
https://justanime.to/contact
|
https://justanime.fun/contact
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-3 leading-relaxed text-base">
|
<p className="mt-3 leading-relaxed text-base">
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function Terms() {
|
|||||||
<div>
|
<div>
|
||||||
<h2 className="text-xl font-semibold text-white mb-4">1. Terms</h2>
|
<h2 className="text-xl font-semibold text-white mb-4">1. Terms</h2>
|
||||||
<p className="leading-relaxed text-base">
|
<p className="leading-relaxed text-base">
|
||||||
By accessing this Website, accessible from https://justanime.to, you are agreeing to be bound by these Website Terms and Conditions of Use and agree that you are responsible for the agreement with any applicable local laws. If you disagree with any of these terms, you are prohibited from accessing this site. The materials contained in this Website are protected by copyright and trade mark law.
|
By accessing this Website, accessible from https://justanime.fun, you are agreeing to be bound by these Website Terms and Conditions of Use and agree that you are responsible for the agreement with any applicable local laws. If you disagree with any of these terms, you are prohibited from accessing this site. The materials contained in this Website are protected by copyright and trade mark law.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -2,62 +2,62 @@ import website_name from "@/src/config/website";
|
|||||||
|
|
||||||
export const generateDescription = (text, maxLength = 155) => {
|
export const generateDescription = (text, maxLength = 155) => {
|
||||||
if (!text) return `Watch anime online free on ${website_name}. Stream English subbed and dubbed anime with no ads.`;
|
if (!text) return `Watch anime online free on ${website_name}. Stream English subbed and dubbed anime with no ads.`;
|
||||||
|
|
||||||
const cleanText = text.replace(/<[^>]*>/g, '');
|
const cleanText = text.replace(/<[^>]*>/g, '');
|
||||||
|
|
||||||
if (cleanText.length <= maxLength) return cleanText;
|
if (cleanText.length <= maxLength) return cleanText;
|
||||||
return cleanText.substring(0, maxLength - 3) + '...';
|
return cleanText.substring(0, maxLength - 3) + '...';
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateKeywords = (animeInfo) => {
|
export const generateKeywords = (animeInfo) => {
|
||||||
const baseKeywords = [website_name.toLowerCase(), 'anime', 'watch online', 'free anime', 'streaming'];
|
const baseKeywords = [website_name.toLowerCase(), 'anime', 'watch online', 'free anime', 'streaming'];
|
||||||
|
|
||||||
if (!animeInfo) return baseKeywords.join(', ');
|
if (!animeInfo) return baseKeywords.join(', ');
|
||||||
|
|
||||||
const keywords = [...baseKeywords];
|
const keywords = [...baseKeywords];
|
||||||
|
|
||||||
if (animeInfo.title) {
|
if (animeInfo.title) {
|
||||||
keywords.push(animeInfo.title.toLowerCase());
|
keywords.push(animeInfo.title.toLowerCase());
|
||||||
keywords.push(animeInfo.title.replace(/[^a-zA-Z0-9 ]/g, '').toLowerCase());
|
keywords.push(animeInfo.title.replace(/[^a-zA-Z0-9 ]/g, '').toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animeInfo.japanese_title) {
|
if (animeInfo.japanese_title) {
|
||||||
keywords.push(animeInfo.japanese_title);
|
keywords.push(animeInfo.japanese_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animeInfo.animeInfo?.genres) {
|
if (animeInfo.animeInfo?.genres) {
|
||||||
keywords.push(...animeInfo.animeInfo.genres.map(g => g.toLowerCase()));
|
keywords.push(...animeInfo.animeInfo.genres.map(g => g.toLowerCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animeInfo.animeInfo?.tvInfo?.showtype) {
|
if (animeInfo.animeInfo?.tvInfo?.showtype) {
|
||||||
keywords.push(animeInfo.animeInfo.tvInfo.showtype.toLowerCase());
|
keywords.push(animeInfo.animeInfo.tvInfo.showtype.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animeInfo.animeInfo?.tvInfo?.sub) {
|
if (animeInfo.animeInfo?.tvInfo?.sub) {
|
||||||
keywords.push('english sub', 'subbed');
|
keywords.push('english sub', 'subbed');
|
||||||
}
|
}
|
||||||
if (animeInfo.animeInfo?.tvInfo?.dub) {
|
if (animeInfo.animeInfo?.tvInfo?.dub) {
|
||||||
keywords.push('english dub', 'dubbed');
|
keywords.push('english dub', 'dubbed');
|
||||||
}
|
}
|
||||||
|
|
||||||
return keywords.slice(0, 15).join(', ');
|
return keywords.slice(0, 15).join(', ');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateCanonicalUrl = (path) => {
|
export const generateCanonicalUrl = (path) => {
|
||||||
const baseUrl = 'https://justanime.to';
|
const baseUrl = 'https://justanime.fun';
|
||||||
if (!path) return baseUrl;
|
if (!path) return baseUrl;
|
||||||
|
|
||||||
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
||||||
return `${baseUrl}${cleanPath}`;
|
return `${baseUrl}${cleanPath}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateOGImage = (imageUrl, fallbackUrl = 'https://i.postimg.cc/kMYmHkPm/home.webp') => {
|
export const generateOGImage = (imageUrl, fallbackUrl = 'https://i.postimg.cc/kMYmHkPm/home.webp') => {
|
||||||
if (!imageUrl) return fallbackUrl;
|
if (!imageUrl) return fallbackUrl;
|
||||||
|
|
||||||
if (imageUrl.startsWith('/')) {
|
if (imageUrl.startsWith('/')) {
|
||||||
return `https://justanime.to${imageUrl}`;
|
return `https://justanime.fun${imageUrl}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageUrl;
|
return imageUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,14 +121,14 @@ export const generateWebsiteStructuredData = () => {
|
|||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "WebSite",
|
"@type": "WebSite",
|
||||||
"name": website_name,
|
"name": website_name,
|
||||||
"alternateName": ["JustAnime.to", "Just Anime"],
|
"alternateName": ["justanime.fun", "Just Anime"],
|
||||||
"url": "https://justanime.to",
|
"url": "https://justanime.fun",
|
||||||
"description": `${website_name} is a free anime streaming website where you can watch English Subbed and Dubbed Anime online.`,
|
"description": `${website_name} is a free anime streaming website where you can watch English Subbed and Dubbed Anime online.`,
|
||||||
"potentialAction": {
|
"potentialAction": {
|
||||||
"@type": "SearchAction",
|
"@type": "SearchAction",
|
||||||
"target": {
|
"target": {
|
||||||
"@type": "EntryPoint",
|
"@type": "EntryPoint",
|
||||||
"urlTemplate": "https://justanime.to/search?keyword={search_term_string}"
|
"urlTemplate": "https://justanime.fun/search?keyword={search_term_string}"
|
||||||
},
|
},
|
||||||
"query-input": "required name=search_term_string"
|
"query-input": "required name=search_term_string"
|
||||||
}
|
}
|
||||||
@@ -159,8 +159,8 @@ export const generateOrganizationStructuredData = () => {
|
|||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
"name": website_name,
|
"name": website_name,
|
||||||
"url": "https://justanime.to",
|
"url": "https://justanime.fun",
|
||||||
"logo": "https://justanime.to/logo.png",
|
"logo": "https://justanime.fun/logo.png",
|
||||||
"sameAs": [
|
"sameAs": [
|
||||||
],
|
],
|
||||||
"contactPoint": {
|
"contactPoint": {
|
||||||
@@ -182,22 +182,22 @@ export const generateAlternateLinks = (currentPath, languages = ['en', 'ja']) =>
|
|||||||
// Clean and optimize title for SEO
|
// Clean and optimize title for SEO
|
||||||
export const optimizeTitle = (title, suffix = true) => {
|
export const optimizeTitle = (title, suffix = true) => {
|
||||||
if (!title) return website_name;
|
if (!title) return website_name;
|
||||||
|
|
||||||
// Remove special characters that might cause issues
|
// Remove special characters that might cause issues
|
||||||
const cleanTitle = title.replace(/[^\w\s\-:,.!?']/g, '').trim();
|
const cleanTitle = title.replace(/[^\w\s\-:,.!?']/g, '').trim();
|
||||||
|
|
||||||
if (suffix) {
|
if (suffix) {
|
||||||
// Keep title under 60 characters total
|
// Keep title under 60 characters total
|
||||||
const suffixText = ` - ${website_name}`;
|
const suffixText = ` - ${website_name}`;
|
||||||
const maxTitleLength = 60 - suffixText.length;
|
const maxTitleLength = 60 - suffixText.length;
|
||||||
|
|
||||||
if (cleanTitle.length > maxTitleLength) {
|
if (cleanTitle.length > maxTitleLength) {
|
||||||
return cleanTitle.substring(0, maxTitleLength - 3) + '...' + suffixText;
|
return cleanTitle.substring(0, maxTitleLength - 3) + '...' + suffixText;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cleanTitle + suffixText;
|
return cleanTitle + suffixText;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cleanTitle.length > 60 ? cleanTitle.substring(0, 57) + '...' : cleanTitle;
|
return cleanTitle.length > 60 ? cleanTitle.substring(0, 57) + '...' : cleanTitle;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -206,11 +206,11 @@ export const generateProfileTitle = (user, isLoggedIn = false) => {
|
|||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
return optimizeTitle('Login to Your Profile | AniList Integration', false);
|
return optimizeTitle('Login to Your Profile | AniList Integration', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user?.name) {
|
if (user?.name) {
|
||||||
return optimizeTitle(`${user.name}'s Anime Profile`);
|
return optimizeTitle(`${user.name}'s Anime Profile`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return optimizeTitle('Your Anime Profile');
|
return optimizeTitle('Your Anime Profile');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -218,34 +218,34 @@ export const generateProfileDescription = (user, isLoggedIn = false) => {
|
|||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
return 'Connect your AniList account to sync your anime library, track watching progress, and manage your anime collection on ' + website_name + '.';
|
return 'Connect your AniList account to sync your anime library, track watching progress, and manage your anime collection on ' + website_name + '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user?.name) {
|
if (user?.name) {
|
||||||
const stats = user.statistics?.anime;
|
const stats = user.statistics?.anime;
|
||||||
let description = `View ${user.name}'s anime profile and collection`;
|
let description = `View ${user.name}'s anime profile and collection`;
|
||||||
|
|
||||||
if (stats) {
|
if (stats) {
|
||||||
if (stats.count) description += ` with ${stats.count} anime entries`;
|
if (stats.count) description += ` with ${stats.count} anime entries`;
|
||||||
if (stats.episodesWatched) description += ` and ${stats.episodesWatched} episodes watched`;
|
if (stats.episodesWatched) description += ` and ${stats.episodesWatched} episodes watched`;
|
||||||
}
|
}
|
||||||
|
|
||||||
description += `. Sync with AniList on ${website_name}.`;
|
description += `. Sync with AniList on ${website_name}.`;
|
||||||
return generateDescription(description);
|
return generateDescription(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `Manage your anime collection, track watching progress, and sync with AniList on ${website_name}.`;
|
return `Manage your anime collection, track watching progress, and sync with AniList on ${website_name}.`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateProfileKeywords = (user, isLoggedIn = false) => {
|
export const generateProfileKeywords = (user, isLoggedIn = false) => {
|
||||||
const baseKeywords = [website_name.toLowerCase(), 'anime profile', 'anilist', 'anime collection', 'anime tracker'];
|
const baseKeywords = [website_name.toLowerCase(), 'anime profile', 'anilist', 'anime collection', 'anime tracker'];
|
||||||
|
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
return [...baseKeywords, 'anilist login', 'anime sync', 'watch list'].join(', ');
|
return [...baseKeywords, 'anilist login', 'anime sync', 'watch list'].join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user?.name) {
|
if (user?.name) {
|
||||||
baseKeywords.push(user.name.toLowerCase(), 'anime statistics', 'watching progress');
|
baseKeywords.push(user.name.toLowerCase(), 'anime statistics', 'watching progress');
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...baseKeywords, 'anime library', 'completed anime', 'plan to watch'].slice(0, 12).join(', ');
|
return [...baseKeywords, 'anime library', 'completed anime', 'plan to watch'].slice(0, 12).join(', ');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -270,7 +270,7 @@ export const generateProfileStructuredData = (user, isLoggedIn = false) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const profileData = {
|
const profileData = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "ProfilePage",
|
"@type": "ProfilePage",
|
||||||
@@ -284,15 +284,15 @@ export const generateProfileStructuredData = (user, isLoggedIn = false) => {
|
|||||||
"sameAs": user?.siteUrl ? [user.siteUrl] : []
|
"sameAs": user?.siteUrl ? [user.siteUrl] : []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (user?.avatar?.large) {
|
if (user?.avatar?.large) {
|
||||||
profileData.mainEntity.image = user.avatar.large;
|
profileData.mainEntity.image = user.avatar.large;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user?.statistics?.anime) {
|
if (user?.statistics?.anime) {
|
||||||
const stats = user.statistics.anime;
|
const stats = user.statistics.anime;
|
||||||
profileData.mainEntity.interactionStatistic = [];
|
profileData.mainEntity.interactionStatistic = [];
|
||||||
|
|
||||||
if (stats.count) {
|
if (stats.count) {
|
||||||
profileData.mainEntity.interactionStatistic.push({
|
profileData.mainEntity.interactionStatistic.push({
|
||||||
"@type": "InteractionCounter",
|
"@type": "InteractionCounter",
|
||||||
@@ -300,16 +300,16 @@ export const generateProfileStructuredData = (user, isLoggedIn = false) => {
|
|||||||
"userInteractionCount": stats.count
|
"userInteractionCount": stats.count
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stats.episodesWatched) {
|
if (stats.episodesWatched) {
|
||||||
profileData.mainEntity.interactionStatistic.push({
|
profileData.mainEntity.interactionStatistic.push({
|
||||||
"@type": "InteractionCounter",
|
"@type": "InteractionCounter",
|
||||||
"interactionType": "WatchAction",
|
"interactionType": "WatchAction",
|
||||||
"userInteractionCount": stats.episodesWatched
|
"userInteractionCount": stats.episodesWatched
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return profileData;
|
return profileData;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -317,29 +317,29 @@ export const generateProfileBreadcrumbs = (user, isLoggedIn = false) => {
|
|||||||
const breadcrumbs = [
|
const breadcrumbs = [
|
||||||
{ name: 'Home', url: '/' }
|
{ name: 'Home', url: '/' }
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
breadcrumbs.push({ name: 'Profile Login', url: '/profile' });
|
breadcrumbs.push({ name: 'Profile Login', url: '/profile' });
|
||||||
} else {
|
} else {
|
||||||
breadcrumbs.push({
|
breadcrumbs.push({
|
||||||
name: user?.name ? `${user.name}'s Profile` : 'Profile',
|
name: user?.name ? `${user.name}'s Profile` : 'Profile',
|
||||||
url: '/profile'
|
url: '/profile'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return generateBreadcrumbStructuredData(breadcrumbs);
|
return generateBreadcrumbStructuredData(breadcrumbs);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Category/Collection page SEO functions
|
// Category/Collection page SEO functions
|
||||||
export const generateCategoryMeta = (categoryName, page = 1, description = null) => {
|
export const generateCategoryMeta = (categoryName, page = 1, description = null) => {
|
||||||
const displayName = categoryName.split('-').map(word =>
|
const displayName = categoryName.split('-').map(word =>
|
||||||
word.charAt(0).toUpperCase() + word.slice(1)
|
word.charAt(0).toUpperCase() + word.slice(1)
|
||||||
).join(' ');
|
).join(' ');
|
||||||
|
|
||||||
const title = optimizeTitle(`${displayName} Anime${page > 1 ? ` - Page ${page}` : ''}`);
|
const title = optimizeTitle(`${displayName} Anime${page > 1 ? ` - Page ${page}` : ''}`);
|
||||||
const desc = description ||
|
const desc = description ||
|
||||||
`Browse and watch ${displayName.toLowerCase()} anime online free. Stream high-quality ${displayName.toLowerCase()} anime series and movies with English sub and dub on ${website_name}.`;
|
`Browse and watch ${displayName.toLowerCase()} anime online free. Stream high-quality ${displayName.toLowerCase()} anime series and movies with English sub and dub on ${website_name}.`;
|
||||||
|
|
||||||
const keywords = [
|
const keywords = [
|
||||||
`${displayName.toLowerCase()} anime`,
|
`${displayName.toLowerCase()} anime`,
|
||||||
`watch ${displayName.toLowerCase()}`,
|
`watch ${displayName.toLowerCase()}`,
|
||||||
@@ -349,36 +349,36 @@ export const generateCategoryMeta = (categoryName, page = 1, description = null)
|
|||||||
'anime online',
|
'anime online',
|
||||||
'free anime'
|
'free anime'
|
||||||
].join(', ');
|
].join(', ');
|
||||||
|
|
||||||
return { title, description: generateDescription(desc), keywords };
|
return { title, description: generateDescription(desc), keywords };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generatePaginationLinks = (basePath, currentPage, totalPages) => {
|
export const generatePaginationLinks = (basePath, currentPage, totalPages) => {
|
||||||
const links = [];
|
const links = [];
|
||||||
|
|
||||||
if (currentPage > 1) {
|
if (currentPage > 1) {
|
||||||
const prevPage = currentPage - 1;
|
const prevPage = currentPage - 1;
|
||||||
links.push({
|
links.push({
|
||||||
rel: 'prev',
|
rel: 'prev',
|
||||||
href: prevPage === 1
|
href: prevPage === 1
|
||||||
? generateCanonicalUrl(basePath)
|
? generateCanonicalUrl(basePath)
|
||||||
: generateCanonicalUrl(`${basePath}?page=${prevPage}`)
|
: generateCanonicalUrl(`${basePath}?page=${prevPage}`)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPage < totalPages) {
|
if (currentPage < totalPages) {
|
||||||
links.push({
|
links.push({
|
||||||
rel: 'next',
|
rel: 'next',
|
||||||
href: generateCanonicalUrl(`${basePath}?page=${currentPage + 1}`)
|
href: generateCanonicalUrl(`${basePath}?page=${currentPage + 1}`)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return links;
|
return links;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateCollectionSchema = (items, collectionName, basePath) => {
|
export const generateCollectionSchema = (items, collectionName, basePath) => {
|
||||||
if (!items || items.length === 0) return null;
|
if (!items || items.length === 0) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "CollectionPage",
|
"@type": "CollectionPage",
|
||||||
@@ -407,7 +407,7 @@ export const generateCollectionSchema = (items, collectionName, basePath) => {
|
|||||||
|
|
||||||
export const generateItemListSchema = (items, listName, baseUrl = '') => {
|
export const generateItemListSchema = (items, listName, baseUrl = '') => {
|
||||||
if (!items || items.length === 0) return null;
|
if (!items || items.length === 0) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "ItemList",
|
"@type": "ItemList",
|
||||||
@@ -428,7 +428,7 @@ export const generateItemListSchema = (items, listName, baseUrl = '') => {
|
|||||||
|
|
||||||
export const generateFAQSchema = (faqs) => {
|
export const generateFAQSchema = (faqs) => {
|
||||||
if (!faqs || faqs.length === 0) return null;
|
if (!faqs || faqs.length === 0) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "FAQPage",
|
"@type": "FAQPage",
|
||||||
@@ -445,12 +445,12 @@ export const generateFAQSchema = (faqs) => {
|
|||||||
|
|
||||||
export const generateAggregateRating = (score, ratingCount = null) => {
|
export const generateAggregateRating = (score, ratingCount = null) => {
|
||||||
if (!score) return null;
|
if (!score) return null;
|
||||||
|
|
||||||
// Parse score (could be "8.5/10" or just "8.5")
|
// Parse score (could be "8.5/10" or just "8.5")
|
||||||
const numericScore = parseFloat(score.toString().split('/')[0]);
|
const numericScore = parseFloat(score.toString().split('/')[0]);
|
||||||
|
|
||||||
if (isNaN(numericScore)) return null;
|
if (isNaN(numericScore)) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"@type": "AggregateRating",
|
"@type": "AggregateRating",
|
||||||
"ratingValue": numericScore.toFixed(1),
|
"ratingValue": numericScore.toFixed(1),
|
||||||
@@ -472,34 +472,34 @@ export const generateOfferSchema = (price = 0) => {
|
|||||||
|
|
||||||
// A-Z List specific SEO
|
// A-Z List specific SEO
|
||||||
export const generateAZListMeta = (letter, page = 1) => {
|
export const generateAZListMeta = (letter, page = 1) => {
|
||||||
const displayLetter = letter === 'az-list' ? 'All' :
|
const displayLetter = letter === 'az-list' ? 'All' :
|
||||||
letter === 'other' ? '#' :
|
letter === 'other' ? '#' :
|
||||||
letter === '0-9' ? '0-9' :
|
letter === '0-9' ? '0-9' :
|
||||||
letter.toUpperCase();
|
letter.toUpperCase();
|
||||||
|
|
||||||
const title = optimizeTitle(`Anime Starting with ${displayLetter}${page > 1 ? ` - Page ${page}` : ''}`);
|
const title = optimizeTitle(`Anime Starting with ${displayLetter}${page > 1 ? ` - Page ${page}` : ''}`);
|
||||||
const description = generateDescription(
|
const description = generateDescription(
|
||||||
`Browse anime titles starting with ${displayLetter}. Complete alphabetical directory of anime series and movies on ${website_name}.`
|
`Browse anime titles starting with ${displayLetter}. Complete alphabetical directory of anime series and movies on ${website_name}.`
|
||||||
);
|
);
|
||||||
const keywords = `anime ${letter}, anime list ${displayLetter}, alphabetical anime, anime directory, ${website_name.toLowerCase()}`;
|
const keywords = `anime ${letter}, anime list ${displayLetter}, alphabetical anime, anime directory, ${website_name.toLowerCase()}`;
|
||||||
|
|
||||||
return { title, description, keywords };
|
return { title, description, keywords };
|
||||||
};
|
};
|
||||||
|
|
||||||
// Search page SEO
|
// Search page SEO
|
||||||
export const generateSearchMeta = (query) => {
|
export const generateSearchMeta = (query) => {
|
||||||
const title = query
|
const title = query
|
||||||
? optimizeTitle(`Search: ${query}`)
|
? optimizeTitle(`Search: ${query}`)
|
||||||
: optimizeTitle('Search Anime');
|
: optimizeTitle('Search Anime');
|
||||||
|
|
||||||
const description = query
|
const description = query
|
||||||
? generateDescription(`Search results for "${query}". Find anime series, movies and more on ${website_name}.`)
|
? generateDescription(`Search results for "${query}". Find anime series, movies and more on ${website_name}.`)
|
||||||
: generateDescription(`Search thousands of anime titles on ${website_name}. Find your favorite anime series and movies.`);
|
: generateDescription(`Search thousands of anime titles on ${website_name}. Find your favorite anime series and movies.`);
|
||||||
|
|
||||||
const keywords = query
|
const keywords = query
|
||||||
? `search anime, find ${query}, anime search, ${query} anime, ${website_name.toLowerCase()}`
|
? `search anime, find ${query}, anime search, ${query} anime, ${website_name.toLowerCase()}`
|
||||||
: `search anime, find anime, anime search, ${website_name.toLowerCase()}`;
|
: `search anime, find anime, anime search, ${website_name.toLowerCase()}`;
|
||||||
|
|
||||||
return { title, description, keywords };
|
return { title, description, keywords };
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -511,10 +511,10 @@ export const generateMusicMeta = (animeName = null, themes = []) => {
|
|||||||
`Listen to opening and ending themes from ${animeName}. ${themes.length > 0 ? `${themes.length} tracks available.` : ''} High quality anime music streaming on ${website_name}.`
|
`Listen to opening and ending themes from ${animeName}. ${themes.length > 0 ? `${themes.length} tracks available.` : ''} High quality anime music streaming on ${website_name}.`
|
||||||
);
|
);
|
||||||
const keywords = `${animeName.toLowerCase()} music, ${animeName.toLowerCase()} opening, ${animeName.toLowerCase()} ending, anime soundtrack, ${website_name.toLowerCase()}`;
|
const keywords = `${animeName.toLowerCase()} music, ${animeName.toLowerCase()} opening, ${animeName.toLowerCase()} ending, anime soundtrack, ${website_name.toLowerCase()}`;
|
||||||
|
|
||||||
return { title, description, keywords };
|
return { title, description, keywords };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: optimizeTitle('Anime Music & Themes'),
|
title: optimizeTitle('Anime Music & Themes'),
|
||||||
description: generateDescription('Listen to your favorite anime opening and ending themes. High quality anime music streaming with comprehensive database.'),
|
description: generateDescription('Listen to your favorite anime opening and ending themes. High quality anime music streaming with comprehensive database.'),
|
||||||
@@ -524,7 +524,7 @@ export const generateMusicMeta = (animeName = null, themes = []) => {
|
|||||||
|
|
||||||
export const generateMusicPlaylistSchema = (animeName, themes = []) => {
|
export const generateMusicPlaylistSchema = (animeName, themes = []) => {
|
||||||
if (!animeName || themes.length === 0) return null;
|
if (!animeName || themes.length === 0) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "MusicPlaylist",
|
"@type": "MusicPlaylist",
|
||||||
|
|||||||
Reference in New Issue
Block a user