diff --git a/README.md b/README.md index ce61444..e6ca57e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- + JustAnime
@@ -16,7 +16,7 @@

- JustAnime is an open-source anime streaming service that uses ANIME 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. + JustAnime is an open-source anime streaming service that uses ANIME 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.

@@ -92,13 +92,13 @@ npm start # or npm run dev (to run develepment server) ### Vercel -Host your own instance of JustAnime on vercel +Host your own instance of JustAnime on vercel [![Deploy to Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/tejaspanchall/JustAnime) ### Render -Host your own instance of JustAnime on Render. +Host your own instance of JustAnime on Render. [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/tejaspanchall/JustAnime) diff --git a/index.html b/index.html index 440f88b..e7cb847 100644 --- a/index.html +++ b/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." /> - + @@ -61,24 +61,24 @@ "@context": "https://schema.org", "@type": "WebSite", "name": "JustAnime", - "alternateName": ["JustAnime.to", "Just Anime"], - "url": "https://justanime.to", + "alternateName": ["justanime.fun", "Just Anime"], + "url": "https://justanime.fun", "description": "JustAnime offers free streaming of English-subbed and dubbed anime series and movies. No account needed and no ads!", "potentialAction": { "@type": "SearchAction", "target": { "@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" }, "publisher": { "@type": "Organization", "name": "JustAnime", - "url": "https://justanime.to", + "url": "https://justanime.fun", "logo": { "@type": "ImageObject", - "url": "https://justanime.to/logo.png", + "url": "https://justanime.fun/logo.png", "width": 512, "height": 512 }, @@ -91,7 +91,7 @@ } - + diff --git a/src/pages/Home/Home.jsx b/src/pages/Home/Home.jsx index 6ad8b8c..2dd6a9e 100644 --- a/src/pages/Home/Home.jsx +++ b/src/pages/Home/Home.jsx @@ -33,11 +33,11 @@ function Home() { {website_name} | Free Anime Streaming Platform - + - + diff --git a/src/pages/dmca/DMCA.jsx b/src/pages/dmca/DMCA.jsx index 11e5b7e..f13bc4f 100644 --- a/src/pages/dmca/DMCA.jsx +++ b/src/pages/dmca/DMCA.jsx @@ -14,10 +14,10 @@ function DMCA() {

- 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. - 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 + 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. + 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 our Contact page, and we will take appropriate action.

@@ -47,11 +47,11 @@ function DMCA() {

Submit Your Request

Your DMCA takedown request should be submit here:{' '} - - https://justanime.to/contact + https://justanime.fun/contact

diff --git a/src/pages/terms/Terms.jsx b/src/pages/terms/Terms.jsx index 5a156cc..2083f16 100644 --- a/src/pages/terms/Terms.jsx +++ b/src/pages/terms/Terms.jsx @@ -13,7 +13,7 @@ function Terms() {

1. Terms

- 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.

diff --git a/src/utils/seo.utils.js b/src/utils/seo.utils.js index fcfdbaa..6914086 100644 --- a/src/utils/seo.utils.js +++ b/src/utils/seo.utils.js @@ -2,62 +2,62 @@ import website_name from "@/src/config/website"; 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.`; - + const cleanText = text.replace(/<[^>]*>/g, ''); - + if (cleanText.length <= maxLength) return cleanText; return cleanText.substring(0, maxLength - 3) + '...'; }; export const generateKeywords = (animeInfo) => { const baseKeywords = [website_name.toLowerCase(), 'anime', 'watch online', 'free anime', 'streaming']; - + if (!animeInfo) return baseKeywords.join(', '); - + const keywords = [...baseKeywords]; - + if (animeInfo.title) { keywords.push(animeInfo.title.toLowerCase()); keywords.push(animeInfo.title.replace(/[^a-zA-Z0-9 ]/g, '').toLowerCase()); } - + if (animeInfo.japanese_title) { keywords.push(animeInfo.japanese_title); } - + if (animeInfo.animeInfo?.genres) { keywords.push(...animeInfo.animeInfo.genres.map(g => g.toLowerCase())); } - + if (animeInfo.animeInfo?.tvInfo?.showtype) { keywords.push(animeInfo.animeInfo.tvInfo.showtype.toLowerCase()); } - + if (animeInfo.animeInfo?.tvInfo?.sub) { keywords.push('english sub', 'subbed'); } if (animeInfo.animeInfo?.tvInfo?.dub) { keywords.push('english dub', 'dubbed'); } - + return keywords.slice(0, 15).join(', '); }; export const generateCanonicalUrl = (path) => { - const baseUrl = 'https://justanime.to'; + const baseUrl = 'https://justanime.fun'; if (!path) return baseUrl; - + const cleanPath = path.startsWith('/') ? path : `/${path}`; return `${baseUrl}${cleanPath}`; }; export const generateOGImage = (imageUrl, fallbackUrl = 'https://i.postimg.cc/kMYmHkPm/home.webp') => { if (!imageUrl) return fallbackUrl; - + if (imageUrl.startsWith('/')) { - return `https://justanime.to${imageUrl}`; + return `https://justanime.fun${imageUrl}`; } - + return imageUrl; }; @@ -121,14 +121,14 @@ export const generateWebsiteStructuredData = () => { "@context": "https://schema.org", "@type": "WebSite", "name": website_name, - "alternateName": ["JustAnime.to", "Just Anime"], - "url": "https://justanime.to", + "alternateName": ["justanime.fun", "Just Anime"], + "url": "https://justanime.fun", "description": `${website_name} is a free anime streaming website where you can watch English Subbed and Dubbed Anime online.`, "potentialAction": { "@type": "SearchAction", "target": { "@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" } @@ -159,8 +159,8 @@ export const generateOrganizationStructuredData = () => { "@context": "https://schema.org", "@type": "Organization", "name": website_name, - "url": "https://justanime.to", - "logo": "https://justanime.to/logo.png", + "url": "https://justanime.fun", + "logo": "https://justanime.fun/logo.png", "sameAs": [ ], "contactPoint": { @@ -182,22 +182,22 @@ export const generateAlternateLinks = (currentPath, languages = ['en', 'ja']) => // Clean and optimize title for SEO export const optimizeTitle = (title, suffix = true) => { if (!title) return website_name; - + // Remove special characters that might cause issues const cleanTitle = title.replace(/[^\w\s\-:,.!?']/g, '').trim(); - + if (suffix) { // Keep title under 60 characters total const suffixText = ` - ${website_name}`; const maxTitleLength = 60 - suffixText.length; - + if (cleanTitle.length > maxTitleLength) { return cleanTitle.substring(0, maxTitleLength - 3) + '...' + suffixText; } - + return cleanTitle + suffixText; } - + return cleanTitle.length > 60 ? cleanTitle.substring(0, 57) + '...' : cleanTitle; }; @@ -206,11 +206,11 @@ export const generateProfileTitle = (user, isLoggedIn = false) => { if (!isLoggedIn) { return optimizeTitle('Login to Your Profile | AniList Integration', false); } - + if (user?.name) { return optimizeTitle(`${user.name}'s Anime Profile`); } - + return optimizeTitle('Your Anime Profile'); }; @@ -218,34 +218,34 @@ export const generateProfileDescription = (user, isLoggedIn = false) => { if (!isLoggedIn) { return 'Connect your AniList account to sync your anime library, track watching progress, and manage your anime collection on ' + website_name + '.'; } - + if (user?.name) { const stats = user.statistics?.anime; let description = `View ${user.name}'s anime profile and collection`; - + if (stats) { if (stats.count) description += ` with ${stats.count} anime entries`; if (stats.episodesWatched) description += ` and ${stats.episodesWatched} episodes watched`; } - + description += `. Sync with AniList on ${website_name}.`; return generateDescription(description); } - + return `Manage your anime collection, track watching progress, and sync with AniList on ${website_name}.`; }; export const generateProfileKeywords = (user, isLoggedIn = false) => { const baseKeywords = [website_name.toLowerCase(), 'anime profile', 'anilist', 'anime collection', 'anime tracker']; - + if (!isLoggedIn) { return [...baseKeywords, 'anilist login', 'anime sync', 'watch list'].join(', '); } - + if (user?.name) { baseKeywords.push(user.name.toLowerCase(), 'anime statistics', 'watching progress'); } - + 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 = { "@context": "https://schema.org", "@type": "ProfilePage", @@ -284,15 +284,15 @@ export const generateProfileStructuredData = (user, isLoggedIn = false) => { "sameAs": user?.siteUrl ? [user.siteUrl] : [] } }; - + if (user?.avatar?.large) { profileData.mainEntity.image = user.avatar.large; } - + if (user?.statistics?.anime) { const stats = user.statistics.anime; profileData.mainEntity.interactionStatistic = []; - + if (stats.count) { profileData.mainEntity.interactionStatistic.push({ "@type": "InteractionCounter", @@ -300,16 +300,16 @@ export const generateProfileStructuredData = (user, isLoggedIn = false) => { "userInteractionCount": stats.count }); } - + if (stats.episodesWatched) { profileData.mainEntity.interactionStatistic.push({ "@type": "InteractionCounter", - "interactionType": "WatchAction", + "interactionType": "WatchAction", "userInteractionCount": stats.episodesWatched }); } } - + return profileData; }; @@ -317,29 +317,29 @@ export const generateProfileBreadcrumbs = (user, isLoggedIn = false) => { const breadcrumbs = [ { name: 'Home', url: '/' } ]; - + if (!isLoggedIn) { breadcrumbs.push({ name: 'Profile Login', url: '/profile' }); } else { - breadcrumbs.push({ - name: user?.name ? `${user.name}'s Profile` : 'Profile', - url: '/profile' + breadcrumbs.push({ + name: user?.name ? `${user.name}'s Profile` : 'Profile', + url: '/profile' }); } - + return generateBreadcrumbStructuredData(breadcrumbs); }; // Category/Collection page SEO functions 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) ).join(' '); - + 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}.`; - + const keywords = [ `${displayName.toLowerCase()} anime`, `watch ${displayName.toLowerCase()}`, @@ -349,36 +349,36 @@ export const generateCategoryMeta = (categoryName, page = 1, description = null) 'anime online', 'free anime' ].join(', '); - + return { title, description: generateDescription(desc), keywords }; }; export const generatePaginationLinks = (basePath, currentPage, totalPages) => { const links = []; - + if (currentPage > 1) { const prevPage = currentPage - 1; links.push({ rel: 'prev', - href: prevPage === 1 + href: prevPage === 1 ? generateCanonicalUrl(basePath) : generateCanonicalUrl(`${basePath}?page=${prevPage}`) }); } - + if (currentPage < totalPages) { links.push({ rel: 'next', href: generateCanonicalUrl(`${basePath}?page=${currentPage + 1}`) }); } - + return links; }; export const generateCollectionSchema = (items, collectionName, basePath) => { if (!items || items.length === 0) return null; - + return { "@context": "https://schema.org", "@type": "CollectionPage", @@ -407,7 +407,7 @@ export const generateCollectionSchema = (items, collectionName, basePath) => { export const generateItemListSchema = (items, listName, baseUrl = '') => { if (!items || items.length === 0) return null; - + return { "@context": "https://schema.org", "@type": "ItemList", @@ -428,7 +428,7 @@ export const generateItemListSchema = (items, listName, baseUrl = '') => { export const generateFAQSchema = (faqs) => { if (!faqs || faqs.length === 0) return null; - + return { "@context": "https://schema.org", "@type": "FAQPage", @@ -445,12 +445,12 @@ export const generateFAQSchema = (faqs) => { export const generateAggregateRating = (score, ratingCount = null) => { if (!score) return null; - + // Parse score (could be "8.5/10" or just "8.5") const numericScore = parseFloat(score.toString().split('/')[0]); - + if (isNaN(numericScore)) return null; - + return { "@type": "AggregateRating", "ratingValue": numericScore.toFixed(1), @@ -472,34 +472,34 @@ export const generateOfferSchema = (price = 0) => { // A-Z List specific SEO export const generateAZListMeta = (letter, page = 1) => { - const displayLetter = letter === 'az-list' ? 'All' : - letter === 'other' ? '#' : - letter === '0-9' ? '0-9' : - letter.toUpperCase(); - + const displayLetter = letter === 'az-list' ? 'All' : + letter === 'other' ? '#' : + letter === '0-9' ? '0-9' : + letter.toUpperCase(); + const title = optimizeTitle(`Anime Starting with ${displayLetter}${page > 1 ? ` - Page ${page}` : ''}`); const description = generateDescription( `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()}`; - + return { title, description, keywords }; }; // Search page SEO export const generateSearchMeta = (query) => { - const title = query + const title = query ? optimizeTitle(`Search: ${query}`) : optimizeTitle('Search Anime'); - + const description = query ? 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.`); - + const keywords = query ? `search anime, find ${query}, anime search, ${query} anime, ${website_name.toLowerCase()}` : `search anime, find anime, anime search, ${website_name.toLowerCase()}`; - + 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}.` ); const keywords = `${animeName.toLowerCase()} music, ${animeName.toLowerCase()} opening, ${animeName.toLowerCase()} ending, anime soundtrack, ${website_name.toLowerCase()}`; - + return { title, description, keywords }; } - + return { title: optimizeTitle('Anime Music & Themes'), 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 = []) => { if (!animeName || themes.length === 0) return null; - + return { "@context": "https://schema.org", "@type": "MusicPlaylist",