diff --git a/next-sitemap.config.js b/next-sitemap.config.js index 5f2b3ce..fd23d65 100644 --- a/next-sitemap.config.js +++ b/next-sitemap.config.js @@ -1,12 +1,31 @@ -const config = { - siteUrl: 'https://www.example.com', - generateRobotsTxt: true, - robotsTxtOptions: { - policies: [ - { userAgent: '*', allow: '/', disallow: ['/api/', '/admin/', '/private/'] }, - ], - }, - }; - - module.exports = config; - \ No newline at end of file +// next-sitemap.config.js +module.exports = { + siteUrl: 'https://duasapp.com', // Replace with your site's URL + generateRobotsTxt: true, // Generates robots.txt alongside the sitemap + changefreq: 'monthly', // Set the frequency of page changes + priority: 0.8, // Default priority for pages + sitemapSize: 5000, // Maximum entries per sitemap file + exclude: ['/admin/*', '/dashboard/*', '/404*'], // Exclude specific paths + additionalPaths: async (config) => { + // Custom static paths + const staticPaths = [ + await config.transform(config, '/about'), + ]; + + // Dynamic Dua paths (replace this with API call or database query in production) + const duaSlugs = ["etiquette-of-reciting-the-request-for-entry", "etiquettes-of-carrying-the-janazah", "dua-abu-hamza-thumali"]; // Example dynamic IDs + const dynamicPaths = duaSlugs.map((slug) => ({ + loc: `/duas/${slug}`, + lastmod: new Date().toISOString(), + changefreq: 'monthly', + priority: 0.9, + })); + + return [...staticPaths, ...dynamicPaths]; + }, + robotsTxtOptions: { + additionalSitemaps: [ + 'https://duasapp.com/sitemap-0.xml', // Add other sitemaps if necessary + ], + }, +}; diff --git a/public/assets/images/Icon_Illustration.webp b/public/assets/images/Icon_Illustration.webp new file mode 100644 index 0000000..8dfc330 Binary files /dev/null and b/public/assets/images/Icon_Illustration.webp differ diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 0609db6..926179f 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -40,5 +40,9 @@ "monthly": "Monthly", "enter_desired_amount": "Enter the desired amount...", "donate_now": "Donate Now", - "credits": "Credits" + "credits": "Credits", + "notFoundImageAlt": "Not Found Illustration", + "ohNo": "Oh No!", + "somethingWentWrong": "Something went wrong!", + "backToHomePage": "Back to Home Page" } diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..960f5b3 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,10 @@ +# * +User-agent: * +Allow: / + +# Host +Host: https://duasapp.com + +# Sitemaps +Sitemap: https://duasapp.com/sitemap.xml +Sitemap: https://duasapp.com/sitemap-0.xml diff --git a/public/sitemap-0.xml b/public/sitemap-0.xml new file mode 100644 index 0000000..e90969b --- /dev/null +++ b/public/sitemap-0.xml @@ -0,0 +1,27 @@ + + +https://duasapp.com2025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/about2025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/es/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/de/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/uz/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/pt/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/bn/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/zh/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/az/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/ur/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/fr/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/tr/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/id/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/sw/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/ru/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/ar/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/tg/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/fa/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/gu/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/ks/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/ha/4042025-01-15T13:11:26.470Zmonthly0.8 +https://duasapp.com/dua/etiquette-of-reciting-the-request-for-entry2025-01-15T13:11:26.470Zdaily0.9 +https://duasapp.com/dua/etiquettes-of-carrying-the-janazah2025-01-15T13:11:26.470Zdaily0.9 +https://duasapp.com/dua/dua-abu-hamza-thumali2025-01-15T13:11:26.470Zdaily0.9 + \ No newline at end of file diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..a763e05 --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,5 @@ + + +https://duasapp.com/sitemap-0.xml +https://duasapp.com/sitemap-0.xml + \ No newline at end of file diff --git a/src/components/common/default-seo.tsx b/src/components/common/default-seo.tsx index 721c561..83a80cb 100644 --- a/src/components/common/default-seo.tsx +++ b/src/components/common/default-seo.tsx @@ -1,3 +1,5 @@ +// components/DefaultSeo.js +import React from "react"; import { DefaultSeo as NextDefaultSeo } from "next-seo"; interface DefaultSeoProps { @@ -12,7 +14,7 @@ interface DefaultSeoProps { const DefaultSeo: React.FC = ({ type = "site", - title = "Dua Site", + title = "Dua's Site", description = "A comprehensive collection of Duas", keywords = "dua, islam, prayer, supplication", url = "https://duasapp.com", @@ -25,38 +27,38 @@ const DefaultSeo: React.FC = ({ ? { "@context": "https://schema.org/", "@type": "WebSite", - "name": title, - "url": url, - "description": description, - "publisher": { + name: title, + url: url, + description: description, + publisher: { "@type": "Organization", - "name": "DuasApp", - "url": url, - "logo": { + name: "DuasApp", + url: url, + logo: { "@type": "ImageObject", - "url": "/assets/images/Hosseiniye.svg", + url: `${url}/assets/images/Hosseiniye.svg`, }, }, - "potentialAction": { + potentialAction: { "@type": "SearchAction", - "target": `${url}/?search={search_term_string}`, + target: `${url}/?search={search_term_string}`, "query-input": "required name=search_term_string", }, - "inLanguage": "en", + inLanguage: "en", } : { "@context": "https://schema.org/", "@type": "CreativeWork", - "name": title, - "url": url, - "description": description, - "text": text, - "translation": { + name: title, + url: url, + description: description, + text: text, + translation: { "@type": "CreativeWork", - "name": "Translation", - "text": translation, + name: "Translation", + text: translation, }, - "keywords": keywords, + keywords: keywords, }; return ( @@ -72,7 +74,7 @@ const DefaultSeo: React.FC = ({ description: description, images: [ { - url: "/assets/images/Hosseiniye.svg", + url: `${url}/assets/images/Hosseiniye.svg`, width: 1200, height: 630, alt: type === "site" ? "Dua Site" : title, @@ -92,7 +94,7 @@ const DefaultSeo: React.FC = ({ charset: "utf-8", }, { - name: "apple-mobile-web-app-capable", + name: "mobile-web-app-capable", content: "yes", }, { diff --git a/src/components/context/audio-conext.tsx b/src/components/context/audio-conext.tsx index 9c1523e..9363803 100644 --- a/src/components/context/audio-conext.tsx +++ b/src/components/context/audio-conext.tsx @@ -79,7 +79,7 @@ export const AudioProvider: React.FC<{ children: ReactNode }> = ({ setAudio(selectedAudio || audioResponse.data.results[0] || null); } catch (error) { - console.error("Error fetching audios:", error); + console.log("Error fetching audios:", error); } }; diff --git a/src/components/layout/header.tsx b/src/components/layout/header.tsx index 243817e..6364f02 100644 --- a/src/components/layout/header.tsx +++ b/src/components/layout/header.tsx @@ -16,7 +16,7 @@ const Header = () => { }`} aria-label="Main Navigation" > -
+
{/* Logo Section */}
diff --git a/src/components/layout/sidebar.tsx b/src/components/layout/sidebar.tsx index fd64757..d2d82ec 100644 --- a/src/components/layout/sidebar.tsx +++ b/src/components/layout/sidebar.tsx @@ -6,14 +6,15 @@ function SideBar() { const router = useRouter(); const params = useParams(); const slug = params?.slug as string; + console.log(router.pathname , router.pathname.includes("/404")); - if (router.pathname.includes("/about") || router.pathname.includes("/last-read")) { + if (router.pathname.includes("/about")) { return null; } return (
diff --git a/src/components/modals/search-modal.tsx b/src/components/modals/search-modal.tsx index 2433467..fb0b25e 100644 --- a/src/components/modals/search-modal.tsx +++ b/src/components/modals/search-modal.tsx @@ -25,8 +25,8 @@ const SearchModal: React.FC = () => { const lastReadDuas = JSON.parse(localStorage.getItem("last-read") || "[]"); const updatedDuas = [...lastReadDuas, dua]; localStorage.setItem("last-read", JSON.stringify(updatedDuas)); - const slug = dua.title.toLowerCase().replaceAll(" ", "-"); - router.push(`/duas/${slug}-${dua.id}`); + const slug = dua.slug + router.push(`/duas/${slug}`); closeModal(); }; diff --git a/src/components/sidebar/categories.tsx b/src/components/sidebar/categories.tsx index 27013d9..2e8f64f 100644 --- a/src/components/sidebar/categories.tsx +++ b/src/components/sidebar/categories.tsx @@ -34,6 +34,7 @@ const Categories: React.FC = ({ { name: category.name, type: "children", data: category.children }, ]); }; +console.log(data); const openDua = (dua: Dua) => { const lastReadDuas = JSON.parse( @@ -41,8 +42,8 @@ const Categories: React.FC = ({ ); const updatedDuas = [...lastReadDuas, dua]; localStorage.setItem("last-read", JSON.stringify(updatedDuas)); - const slug = dua.title.toLowerCase().replaceAll(" ", "-"); - router.push(`/duas/${slug}-${dua.id}`); + const slug = dua.slug + router.push(`/duas/${slug}`); }; useEffect(() => { diff --git a/src/components/sidebar/famous.tsx b/src/components/sidebar/famous.tsx index ddbeeb5..a33013f 100644 --- a/src/components/sidebar/famous.tsx +++ b/src/components/sidebar/famous.tsx @@ -22,8 +22,8 @@ const Famous: React.FC = () => { const lastReadDuas = JSON.parse(localStorage.getItem("last-read") || "[]"); const updatedDuas = [...lastReadDuas, dua]; localStorage.setItem("last-read", JSON.stringify(updatedDuas)); - const slug = dua.title.toLowerCase().replaceAll(" ", "-"); - router.push(`/duas/${slug}-${dua.id}`); + const slug = dua.slug + router.push(`/duas/${slug}`); }; useEffect(() => { diff --git a/src/components/sidebar/nearby.tsx b/src/components/sidebar/nearby.tsx index a3166ba..d5e331d 100644 --- a/src/components/sidebar/nearby.tsx +++ b/src/components/sidebar/nearby.tsx @@ -19,8 +19,8 @@ const NearBy = () => { const lastReadDuas = JSON.parse(localStorage.getItem("last-read") || "[]"); const updatedDuas = [...lastReadDuas, dua]; localStorage.setItem("last-read", JSON.stringify(updatedDuas)); - const slug = dua.title.toLowerCase().replaceAll(" ", "-"); - router.push(`/duas/${slug}-${dua.id}`); + const slug = dua.slug + router.push(`/duas/${slug}`); }; const onClick = () => { // Check if geolocation is available diff --git a/src/components/sidebar/search.tsx b/src/components/sidebar/search.tsx index d5c2e15..2c6bab4 100644 --- a/src/components/sidebar/search.tsx +++ b/src/components/sidebar/search.tsx @@ -23,8 +23,8 @@ const Search: React.FC = () => { const lastReadDuas = JSON.parse(localStorage.getItem("last-read") || "[]"); const updatedDuas = [...lastReadDuas, dua]; localStorage.setItem("last-read", JSON.stringify(updatedDuas)); - const slug = dua.title.toLowerCase().replaceAll(" ", "-"); - router.push(`/duas/${slug}-${dua.id}`); + const slug = dua.slug + router.push(`/duas/${slug}`); }; useEffect(() => { diff --git a/src/components/sidebar/tabs.tsx b/src/components/sidebar/tabs.tsx index 1193236..1755802 100644 --- a/src/components/sidebar/tabs.tsx +++ b/src/components/sidebar/tabs.tsx @@ -66,13 +66,13 @@ const Tabs = () => { path.map((item, index) => { if (item.name && index + 1 < path.length && index > 0) { return ( - + handlePathClick(index)}> {item.name} - + ); } else { diff --git a/src/components/sidebar/today.tsx b/src/components/sidebar/today.tsx index 75ec2e2..dc1126a 100644 --- a/src/components/sidebar/today.tsx +++ b/src/components/sidebar/today.tsx @@ -58,8 +58,8 @@ const Today: React.FC = () => { const lastReadDuas = JSON.parse(localStorage.getItem("last-read") || "[]"); const updatedDuas = [...lastReadDuas, dua]; localStorage.setItem("last-read", JSON.stringify(updatedDuas)); - const slug = dua.title.toLowerCase().replaceAll(" ", "-"); - router.push(`/duas/${slug}-${dua.id}`); + const slug = dua.slug + router.push(`/duas/${slug}`); }; useEffect(() => { diff --git a/src/pages/404.tsx b/src/pages/404.tsx new file mode 100644 index 0000000..cf13a3c --- /dev/null +++ b/src/pages/404.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import Link from "next/link"; +import notFound from "../../public/assets/images/Icon_Illustration.webp"; +import Image from "next/image"; +import { serverSideTranslations } from "next-i18next/serverSideTranslations"; +import { useTranslation } from "next-i18next"; + +const NotFound: React.FC = () => { + const { t } = useTranslation("common"); + + return ( +
+
+ {t("notFoundImageAlt")} +

{t("ohNo")}

+

{t("somethingWentWrong")}

+
+ {t("backToHomePage")} +
+
+
+ ); +}; + +export async function getStaticProps({ locale }) { + return { + props: { + ...(await serverSideTranslations(locale, ["common", "footer"])), + // Will be passed to the page component as props + }, + }; +} + +export default NotFound; diff --git a/src/pages/duas/[slug].tsx b/src/pages/duas/[slug].tsx index becb6b8..7006170 100644 --- a/src/pages/duas/[slug].tsx +++ b/src/pages/duas/[slug].tsx @@ -15,6 +15,7 @@ import { useFontSettingsContext } from "@/components/context/font-setting-contex import { useAudio } from "@/components/context/audio-conext"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { DefaultSeo } from "next-seo"; +import NotFound from "../404"; // Define the Dua interface interface Dua { @@ -64,7 +65,7 @@ const DuaComponent: React.FC = ({ async (nextPage) => { if (!slug || fetching) return; // Prevent fetching if data is already being fetched - const id = slug.split("-").pop(); + const id = slug; if (!id) return; setFetching(true); // Set fetching to true when data starts fetching @@ -82,14 +83,17 @@ const DuaComponent: React.FC = ({ // Append the new results to the existing duaParts setDuaParts((prev) => [...prev, ...duaResponse.data.results]); + console.log(duaResponse); + getAudio(id); + } catch (error) { - console.error("Error fetching Dua parts:", error); + router.replace("/404") + console.log("Error fetching Dua parts:", error); } finally { setLoading(false); setFetching(false); // Reset fetching state after fetching is done } - getAudio(id); }, [slug, fetching, duaParts, getAudio] ); // Dependencies for fetchData @@ -237,12 +241,13 @@ const DuaComponent: React.FC = ({ }, [fetching] ); - + console.log(duaParts[0]?.seo_field); + if (!slug) { return null; // Handling the case where slug is not available } - const title = processSlug(slug); // Title derived from slug - const description = "This is a detailed description for the specific Dua page."; // You can customize this further + const title = duaParts[0]?.seo_field?.title // Title derived from slug + const description = duaParts[0]?.seo_field?.description; // You can customize this further const keywords = "dua, islam, prayer, supplication, dua parts"; // Keywords for SEO return (