diff --git a/LICENSE b/LICENSE index fd21461..edbe91e 100755 --- a/LICENSE +++ b/LICENSE @@ -1,19 +1,153 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ +PolyForm Shield License 1.0.0 -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + -Copyright 2025 Sohan Rout +Required Notice: Copyright 2025 Sohan Rout (https://dsavisualizer.in) -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at +## Acceptance - http://www.apache.org/licenses/LICENSE-2.0 +In order to get any license under these terms, you must agree +to them as both strict obligations and conditions to all +your licenses. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. \ No newline at end of file +## Copyright License + +The licensor grants you a copyright license for the +software to do everything you might do with the software +that would otherwise infringe the licensor's copyright +in it for any permitted purpose. However, you may +only distribute the software according to Distribution +License and make changes or new works based on the +software according to Changes and New Works License. + +## Distribution License + +The licensor grants you an additional copyright license +to distribute copies of the software. Your license +to distribute covers distributing the software with +changes and new works permitted by Changes and New +Works License. + +## Notices + +You must ensure that anyone who gets a copy of any part +of the software from you also gets a copy of these +terms or the URL for them above, as well as copies of +any plain-text lines beginning with `Required Notice:` +that the licensor provided with the software. For +example: + +> Required Notice: Copyright 2025 Sohan Rout (https://dsavisualizer.in) + +## Changes and New Works License + +The licensor grants you an additional copyright license +to make changes and new works based on the software +for any permitted purpose. + +## Patent License + +The licensor grants you a patent license for the +software that covers patent claims the licensor can +license, or becomes able to license, that you would +infringe by using the software. + +## Noncompete + +Any purpose is a permitted purpose, except for providing +any product that competes with the software or any +product the licensor or any of its affiliates provides +using the software. + +## Competition + +Goods and services compete even when they provide +functionality through different kinds of interfaces +or media. Goods and services can compete even when +provided free of charge. If you market a product as a +practical substitute for the software or another +product, it competes with that product, even if you +market it for a different purpose or context. + +## New Products + +If you are using the software to provide a product that +does not compete with the software, but the licensor or +any of its affiliates brings a new product to market +that competes with the software and directly +competes with your product, you may continue to +distribute your existing products that use the software, +but you may not create new products that use the +software. + +## Discontinued Products + +You may begin using the software to compete with a +product or service that the licensor or any of its +affiliates has stopped providing, unless the licensor +includes a notice of intent to resume providing the +product or service in the notice or repository +description. + +## Fair Use + +You may have "fair use" rights for the software under +the law. These terms do not limit them. + +## No Other Rights + +These terms do not allow you to sublicense or transfer +any of your licenses to anyone else, or prevent the +licensor from granting licenses to anyone else. These +terms do not imply any other licenses. + +## Patent Defense + +If you make any written claim that the software +infringes or contributes to infringement of any patent, +your patent license for the software granted under these +terms ends immediately. If your company makes such a +claim, your patent license ends immediately for work on +behalf of your company. + +## Violations + +The first time you are notified in writing that you +have violated any of these terms, or done anything with +the software not covered by your licenses, your licenses +can nonetheless continue if you come into full compliance +with these terms, and take practical steps to correct +past violations, within 32 days of receiving notice. +Otherwise, all your licenses end immediately. + +## No Liability + +As far as the law allows, the software comes as is, +without any warranty or condition, and the licensor +will not be liable to you for any damages arising out of +these terms or the use or nature of the software, under +any kind of legal claim. + +## Definitions + +The "licensor" is the individual or entity offering +these terms, and the "software" is the software the +licensor makes available under these terms. + +"You" refers to the individual or entity agreeing to +these terms. + +"Your company" is any legal entity, sole proprietorship, +or other kind of organization that you work for, plus +all organizations that have control over, are under the +control of, or are under common control with that +organization. Control means ownership of substantially +all the assets of an entity, or the power to direct its +management and policies by vote, contract, or otherwise. +Control can be direct or indirect. + +"Your licenses" are all the licenses granted to you for +the software under these terms. + +"Use" means anything you do with the software requiring +one of your licenses. diff --git a/NOTICE b/NOTICE new file mode 100755 index 0000000..715242a --- /dev/null +++ b/NOTICE @@ -0,0 +1,58 @@ +DSA Visualizer +Copyright 2025 Sohan Rout +https://dsavisualizer.in + +## License + +As of 2026, this project is licensed under the PolyForm Shield License +1.0.0 (see LICENSE). This is NOT a standard permissive open-source +license. It allows you to view, run, modify, and self-host this code +for any purpose EXCEPT to build, launch, or operate a product or +service that competes with DSA Visualizer. See LICENSE for the full, +binding terms — this file is a plain-language summary, not a +substitute for it. + +Code obtained from this repository before this NOTICE was added may +have been distributed under the project's prior Apache License 2.0 +terms; those terms do not carry forward to any new copies, forks, or +distributions made after this change. + +## Brand and content — not licensed at all + +Separately from the code license, the following are NOT licensed to +you under any version of this project's license and remain the sole +property of Sohan Rout: + + - The "DSA Visualizer" name, wordmark, and logo + - The site's color scheme, layout, and visual identity as a + distinctive whole + - Original written content: blog posts, page copy, marketing copy, + FAQ answers, and any other prose + - SEO metadata, structured data (JSON-LD), page titles/descriptions, + and Open Graph content + +You may not republish, mirror, or reuse any of the above — in whole +or in part, modified or unmodified — under a different identity, on a +different domain, or in a way that suggests your product is DSA +Visualizer, is affiliated with it, or is endorsed by Sohan Rout. + +## Strict rules for anyone reusing this repository + +1. You must retain this NOTICE and the LICENSE file, unmodified, in + any copy or fork. +2. You must not use the DSA Visualizer name, logo, brand colors, or + layout in a way likely to cause confusion with the original. +3. You must not copy blog posts, page copy, or SEO/meta content + verbatim or near-verbatim and present it as your own. +4. You must not build a competing DSA-learning/visualization product + using this code, per the Noncompete clause in LICENSE. +5. Any violation is grounds for a DMCA takedown, hosting-provider + abuse report, trademark complaint, and/or legal action, in addition + to termination of your license under LICENSE Section "Violations." + +## Reporting a violation + +If you believe someone has copied this project's code, brand, or +content in violation of these terms, contact: + + sohanrout84@gmail.com diff --git a/README.md b/README.md index 16f735b..e2a3536 100755 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ ---

- License: Apache 2.0 + License: PolyForm Shield 1.0.0

Product Built Using:

@@ -51,7 +51,16 @@ ## License -Apache 2.0 License — See `LICENSE` for details. +**PolyForm Shield License 1.0.0** — See [`LICENSE`](./LICENSE) for the full, binding terms. + +This is **not** a permissive open-source license. In short: + +- ✅ You may view, run, modify, and self-host this code for almost any purpose. +- ❌ You may **not** use it to build, launch, or operate a product or service that competes with DSA Visualizer. +- ❌ You may **not** use the "DSA Visualizer" name, logo, brand colors/layout, or original written content (blog posts, page copy, SEO metadata) to represent your project as DSA Visualizer or as affiliated with/endorsed by Sohan Rout — none of that is licensed to you at all, under any circumstance. +- ✅ You must keep the `LICENSE` and [`NOTICE`](./NOTICE) files intact in any copy or fork. + +Violating these terms ends your license immediately (see `LICENSE`) and may result in a DMCA takedown, hosting-provider abuse report, trademark complaint, and/or legal action. Full details and strict rules are in [`NOTICE`](./NOTICE). To report a violation, contact sohanrout2@gmail.com. # Contribution diff --git a/app/components/PrivacyPolicyModal.jsx b/app/components/PrivacyPolicyModal.jsx deleted file mode 100755 index 6c62a7a..0000000 --- a/app/components/PrivacyPolicyModal.jsx +++ /dev/null @@ -1,125 +0,0 @@ -import React, { useEffect } from 'react'; -import { FiX } from 'react-icons/fi'; - -const policySections = [ - { - id : "1", - title : "Information We Collect", - data : "We collect personal information like name, email address, and usage data (IP, browser, etc.) to provide and improve our services.", - }, - { - id : "2", - title : "How We Use Your Information", - points : [ - "To provide and maintain our services", - "Improve user experience and service quality", - "Send important updates or support emails", - ], - }, - { - id : "3", - title : "Your Rights", - data : "You have the right to request access, correction, or deletion of your personal data at any time by contacting us.", - }, - { - id : "4", - title : "Contact Information", - data : "For any privacy-related questions, please contact us at", - contact : "hello@dsavisualizer.in", - }, -]; - -const PrivacyPolicyModal = ({ isOpen, onClose }) => { - // Prevent body scroll when modal is open - useEffect(() => { - if (isOpen) { - document.body.style.overflow = 'hidden'; - } else { - document.body.style.overflow = 'auto'; - } - return () => { - document.body.style.overflow = 'auto'; - }; - }, [isOpen]); - - if (!isOpen) return null; - - return ( -
- {/* Backdrop with fade-in animation */} -
- - {/* Modal container with slide-up animation */} -
- {/* Header with close button */} -
-

- Privacy Policy -

- -
- - {/* Scrollable content */} -
-

- Your privacy is important to us. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you visit our website or use our services. -

- - {/* Policy sections */} -
-
    - {policySections.map((item, index) => ( -
  • -
    -
    - {item.id} -

    - {item.title} -

    -
    - {item.points &&
      - {item.points.map((subitem, subindex) => ( -
    • - {subitem} -
    • - ))} -
    } -

    {item.data}

    - {item.contact} -
    -
  • - ))} -
-
- -
-

- Last updated: May 17, 2025 -

-
-
- - {/* Footer with close button */} -
- -
-
-
- ); -}; - -export default PrivacyPolicyModal; \ No newline at end of file diff --git a/app/components/ads/InContentAd.jsx b/app/components/ads/InContentAd.jsx new file mode 100755 index 0000000..fe8ef1c --- /dev/null +++ b/app/components/ads/InContentAd.jsx @@ -0,0 +1,46 @@ +"use client"; +import { useEffect } from "react"; + +const AD_SCRIPT_ID = "adsbygoogle-js"; +const AD_CLIENT = "ca-pub-4311738896428559"; +const DEFAULT_SLOT = "1111111111"; + +function loadAdSenseScript() { + if (typeof window === "undefined") return; + if (document.getElementById(AD_SCRIPT_ID)) return; + const script = document.createElement("script"); + script.id = AD_SCRIPT_ID; + script.async = true; + script.src = `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${AD_CLIENT}`; + script.crossOrigin = "anonymous"; + document.head.appendChild(script); +} + +const InContentAd = ({ slot = DEFAULT_SLOT }) => { + useEffect(() => { + loadAdSenseScript(); + try { + (window.adsbygoogle = window.adsbygoogle || []).push({}); + } catch (e) { + console.warn("AdSense error:", e); + } + }, []); + + return ( +
+ + Advertisement + + +
+ ); +}; + +export default InContentAd; diff --git a/app/components/cookie.jsx b/app/components/cookie.jsx deleted file mode 100755 index 291d7f5..0000000 --- a/app/components/cookie.jsx +++ /dev/null @@ -1,169 +0,0 @@ -import React, { useEffect } from 'react'; -import { FiX } from 'react-icons/fi'; - -const cookieSections = [ - { - id: "1", - title: "What Are Cookies", - data: "Cookies are small text files that are stored on your device when you visit our website. They help us provide you with a better experience by remembering your preferences and understanding how you use our site.", - }, - { - id: "2", - title: "Types of Cookies We Use", - points: [ - "Essential Cookies: Required for basic site functionality and security", - "Performance Cookies: Help us understand how visitors interact with our website", - "Functionality Cookies: Remember your preferences and settings", - "Analytics Cookies: Collect information about your usage patterns", - ], - }, - { - id: "3", - title: "How We Use Cookies", - points: [ - "To authenticate users and prevent fraudulent use", - "Remember your preferences and settings", - "Analyze site traffic and usage patterns", - "Improve our website performance and user experience", - "Provide personalized content when available", - ], - }, - { - id: "4", - title: "Third-Party Cookies", - data: "We may also use cookies from trusted third-party services for analytics, performance monitoring, and other functionality. These third parties have their own privacy policies governing cookie usage.", - }, - { - id: "5", - title: "Cookie Management", - points: [ - "You can control cookie settings through your browser preferences", - "Most browsers allow you to refuse or delete cookies", - "Disabling essential cookies may affect website functionality", - "You can opt-out of analytics cookies using our cookie preferences tool", - ], - }, - { - id: "6", - title: "Your Choices", - data: "You have the right to accept or reject cookies. Most web browsers automatically accept cookies, but you can usually modify your browser setting to decline cookies if you prefer. However, this may prevent you from taking full advantage of the website.", - }, - { - id: "7", - title: "Updates to Cookie Policy", - data: "We may update this Cookie Policy from time to time to reflect changes in technology, legislation, or our operations. We encourage you to periodically review this page for the latest information.", - }, - { - id: "8", - title: "Contact Information", - data: "If you have any questions about our use of cookies, please contact us at", - contact: "hello@dsavisualizer.in", - }, -]; - -const CookiePolicyModal = ({ isOpen, onClose }) => { - // Prevent body scroll when modal is open - useEffect(() => { - if (isOpen) { - document.body.style.overflow = 'hidden'; - } else { - document.body.style.overflow = 'auto'; - } - return () => { - document.body.style.overflow = 'auto'; - }; - }, [isOpen]); - - if (!isOpen) return null; - - return ( -
- {/* Backdrop with fade-in animation */} -
- - {/* Modal container with slide-up animation */} -
- {/* Header with close button */} -
-

- Cookie Policy -

- -
- - {/* Scrollable content */} -
-

- This Cookie Policy explains how we use cookies and similar technologies on our website. It describes the types of cookies we use, their purposes, and how you can manage your cookie preferences. -

- - {/* Cookie policy sections */} -
-
    - {cookieSections.map((item, index) => ( -
  • -
    -
    - {item.id} -

    - {item.title} -

    -
    - {item.points &&
      - {item.points.map((subitem, subindex) => ( -
    • - {subitem} -
    • - ))} -
    } -

    {item.data}

    - {item.contact && ( - {item.contact} - )} -
    -
  • - ))} -
-
- - {/* Additional cookie information */} -
-

- 🍪 Cookie Duration -

-

- Session cookies are temporary and expire when you close your browser. Persistent cookies remain on your device for a set period or until you delete them. -

-
- -
-

- Last updated: May 17, 2025 -

-
-
- - {/* Footer with close button */} -
- -
-
-
- ); -}; - -export default CookiePolicyModal; \ No newline at end of file diff --git a/app/components/footer.jsx b/app/components/footer.jsx index 645b3b5..8bd531d 100755 --- a/app/components/footer.jsx +++ b/app/components/footer.jsx @@ -1,10 +1,6 @@ "use client"; import React from "react"; import Link from "next/link"; -import { useState } from "react"; -import PrivacyPolicyModal from "@/app/components/PrivacyPolicyModal"; -import TermsOfServiceModal from "@/app/components/termsOfServicesModal"; -import CookiePolicyModal from "@/app/components/cookie"; import { GoHomeFill } from "react-icons/go"; import { MdAnimation } from "react-icons/md"; import { IoMdInformationCircle } from "react-icons/io"; @@ -12,10 +8,6 @@ import { HiSparkles } from "react-icons/hi2"; import { RiQuestionLine } from "react-icons/ri"; const Footer = () => { - const [showPolicyModal, setShowPolicyModal] = useState(false); - const [showTermsModal, setShowTermsModal] = useState(false); - const [showCookieModal, setShowCookieModal] = useState(false); - const quickLinks = [ { href: "/", text: "Home", icon: GoHomeFill }, { href: "/#features", text: "Features", icon: HiSparkles }, @@ -72,9 +64,9 @@ const Footer = () => { ]; const legalLinks = [ - { href: "/privacy", text: "Privacy Policy", type: "policyModal" }, - { href: "/terms", text: "Terms of Service", type: "termsModal" }, - { href: "/cookies", text: "Cookies", type: "cookieModal" }, + { href: "/privacy", text: "Privacy Policy" }, + { href: "/terms", text: "Terms of Service" }, + { href: "/cookies", text: "Cookies" }, ]; return ( @@ -165,63 +157,17 @@ const Footer = () => {
    {legalLinks.map((link, index) => (
  • - {link.type === "policyModal" ? ( - - ) : - link.type === "termsModal" ? ( - - ) - : - link.type === "cookieModal" ? ( - - ) - : - ( - - {link.text} - - )} + + {link.text} +
  • ))}
- {/* Render the modal */} - setShowPolicyModal(false)} - /> - - {/* Render the modal */} - setShowTermsModal(false)} - /> - - {/* Render the modal */} - setShowCookieModal(false)} - /> -

Connect diff --git a/app/components/modules/Header.jsx b/app/components/modules/Header.jsx new file mode 100755 index 0000000..4bd3026 --- /dev/null +++ b/app/components/modules/Header.jsx @@ -0,0 +1,24 @@ +import Breadcrumbs from "@/app/components/ui/Breadcrumbs"; +import ArticleActions from "@/app/components/ui/ArticleActions"; + +export default function ModuleHeader({ category, title, paths }) { + return ( + <> +
+ +
+
+
+

+ {category} +

+
+

+ {title} +

+ +
+
+ + ); +} diff --git a/app/components/policy/PolicyContent.jsx b/app/components/policy/PolicyContent.jsx new file mode 100755 index 0000000..fd2f38a --- /dev/null +++ b/app/components/policy/PolicyContent.jsx @@ -0,0 +1,53 @@ +const PolicyContent = ({ intro, sections, lastUpdated }) => { + return ( +
+

{intro}

+ +
    + {sections.map((item, index) => ( +
  • +
    +
    + + {item.id} + +

    + {item.title} +

    +
    + {item.data && ( +

    + {item.data} +

    + )} + {item.points && ( +
      + {item.points.map((subitem, subindex) => ( +
    • + + {subitem} + +
    • + ))} +
    + )} + {item.contact && ( + + {item.contact} + + )} +
    +
  • + ))} +
+ +
+

+ Last updated: {lastUpdated} +

+
+
+ ); +}; + +export default PolicyContent; diff --git a/app/components/termsOfServicesModal.jsx b/app/components/termsOfServicesModal.jsx deleted file mode 100755 index 9c9ca13..0000000 --- a/app/components/termsOfServicesModal.jsx +++ /dev/null @@ -1,152 +0,0 @@ -import React, { useEffect } from 'react'; -import { FiX } from 'react-icons/fi'; - -const termsSections = [ - { - id: "1", - title: "Acceptance of Terms", - data: "By accessing and using this website, you accept and agree to be bound by the terms and provision of this agreement.", - }, - { - id: "2", - title: "Use License", - points: [ - "Permission is granted to temporarily use the materials on this website for personal, non-commercial transitory viewing only", - "This is the grant of a license, not a transfer of title", - "You may not modify or copy the materials, use them for any commercial purpose, or remove any copyright or proprietary notations", - ], - }, - { - id: "3", - title: "User Responsibilities", - points: [ - "Provide accurate and complete information when required", - "Maintain the confidentiality of your account credentials", - "Notify us immediately of any unauthorized use of your account", - "Use the service in compliance with all applicable laws and regulations", - ], - }, - { - id: "4", - title: "Intellectual Property", - data: "All content, features, and functionality on this website, including but not limited to text, graphics, logos, and software, are the exclusive property of the company and are protected by international copyright, trademark, and other intellectual property laws.", - }, - { - id: "5", - title: "Limitation of Liability", - data: "In no event shall the company, nor its directors, employees, partners, agents, suppliers, or affiliates, be liable for any indirect, incidental, special, consequential or punitive damages, including without limitation, loss of profits, data, use, goodwill, or other intangible losses.", - }, - { - id: "6", - title: "Governing Law", - data: "These Terms shall be governed and construed in accordance with the laws of the applicable jurisdiction, without regard to its conflict of law provisions.", - }, - { - id: "7", - title: "Changes to Terms", - data: "We reserve the right, at our sole discretion, to modify or replace these Terms at any time. By continuing to access or use our service after those revisions become effective, you agree to be bound by the revised terms.", - }, - { - id: "8", - title: "Contact Information", - data: "If you have any questions about these Terms, please contact us at", - contact: "hello@dsavisualizer.in", - }, -]; - -const TermsOfServiceModal = ({ isOpen, onClose }) => { - // Prevent body scroll when modal is open - useEffect(() => { - if (isOpen) { - document.body.style.overflow = 'hidden'; - } else { - document.body.style.overflow = 'auto'; - } - return () => { - document.body.style.overflow = 'auto'; - }; - }, [isOpen]); - - if (!isOpen) return null; - - return ( -
- {/* Backdrop with fade-in animation */} -
- - {/* Modal container with slide-up animation */} -
- {/* Header with close button */} -
-

- Terms of Service -

- -
- - {/* Scrollable content */} -
-

- Please read these terms and conditions carefully before using our website and services. Your access to and use of the service is conditioned on your acceptance of and compliance with these terms. -

- - {/* Terms sections */} -
-
    - {termsSections.map((item, index) => ( -
  • -
    -
    - {item.id} -

    - {item.title} -

    -
    - {item.points &&
      - {item.points.map((subitem, subindex) => ( -
    • - {subitem} -
    • - ))} -
    } -

    {item.data}

    - {item.contact && ( - {item.contact} - )} -
    -
  • - ))} -
-
- -
-

- Last updated: May 17, 2025 -

-
-
- - {/* Footer with close button */} -
- -
-
-
- ); -}; - -export default TermsOfServiceModal; \ No newline at end of file diff --git a/app/components/ui/NewsletterEmbed.jsx b/app/components/ui/NewsletterEmbed.jsx old mode 100644 new mode 100755 diff --git a/app/cookies/page.jsx b/app/cookies/page.jsx new file mode 100755 index 0000000..b3fe4da --- /dev/null +++ b/app/cookies/page.jsx @@ -0,0 +1,111 @@ +import Navbar from "@/app/components/navbar"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; +import ModuleHeader from "@/app/components/modules/Header"; +import PolicyContent from "@/app/components/policy/PolicyContent"; + +export const metadata = { + title: "Cookie Policy | DSA Visualizer", + description: + "Read the DSA Visualizer Cookie Policy to learn what cookies we use, why we use them, and how you can manage your cookie preferences.", + robots: "index, follow", +}; + +const cookieSections = [ + { + id: "1", + title: "What Are Cookies", + data: "Cookies are small text files that are stored on your device when you visit our website. They help us provide you with a better experience by remembering your preferences and understanding how you use our site.", + }, + { + id: "2", + title: "Types of Cookies We Use", + points: [ + "Essential Cookies: Required for basic site functionality and security", + "Performance Cookies: Help us understand how visitors interact with our website", + "Functionality Cookies: Remember your preferences and settings", + "Analytics Cookies: Collect information about your usage patterns", + ], + }, + { + id: "3", + title: "How We Use Cookies", + points: [ + "To authenticate users and prevent fraudulent use", + "Remember your preferences and settings", + "Analyze site traffic and usage patterns", + "Improve our website performance and user experience", + "Provide personalized content when available", + ], + }, + { + id: "4", + title: "Third-Party Cookies", + data: "We use cookies from the following third-party services, each governed by its own privacy policy:", + points: [ + "Google Analytics — measures site traffic and usage patterns", + "Google AdSense — serves ads and may use cookies to personalize ads based on your visits to this and other sites", + "Supabase — sets authentication cookies to keep you signed in", + "Cloudflare Turnstile — sets cookies to verify you're not a bot on login and signup", + ], + }, + { + id: "5", + title: "Cookie Management", + points: [ + "You can control cookie settings through your browser preferences", + "Most browsers allow you to refuse or delete cookies", + "Disabling essential cookies may affect website functionality, such as staying signed in", + "You can opt out of Google Analytics using the Google Analytics Opt-out Browser Add-on, and manage Google ad personalization at adssettings.google.com", + ], + }, + { + id: "6", + title: "Your Choices", + data: "You have the right to accept or reject cookies. Most web browsers automatically accept cookies, but you can usually modify your browser setting to decline cookies if you prefer. However, this may prevent you from taking full advantage of the website.", + }, + { + id: "7", + title: "Updates to Cookie Policy", + data: "We may update this Cookie Policy from time to time to reflect changes in technology, legislation, or our operations. We encourage you to periodically review this page for the latest information.", + }, + { + id: "8", + title: "Contact Information", + data: "If you have any questions about our use of cookies, please contact us at", + contact: "hello@dsavisualizer.in", + }, +]; + +export default function CookiePolicyPage() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Cookie Policy", href: "" }, + ]; + + return ( + <> +
+ +
+ +
+
+ + +
+
+ + +
+ + ); +} diff --git a/app/privacy/page.jsx b/app/privacy/page.jsx new file mode 100755 index 0000000..d1a4edb --- /dev/null +++ b/app/privacy/page.jsx @@ -0,0 +1,107 @@ +import Navbar from "@/app/components/navbar"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; +import ModuleHeader from "@/app/components/modules/Header"; +import PolicyContent from "@/app/components/policy/PolicyContent"; + +export const metadata = { + title: "Privacy Policy | DSA Visualizer", + description: + "Read the DSA Visualizer Privacy Policy to learn how we collect, use, and protect your information when you use our interactive DSA learning platform.", + robots: "index, follow", +}; + +const policySections = [ + { + id: "1", + title: "Information We Collect", + points: [ + "Account information: name, email address, and authentication data when you sign up or log in (including via Google sign-in), handled through our authentication provider, Supabase", + "Usage data: pages visited, modules completed, and progress data, so we can show your dashboard and activity history", + "Technical data: IP address, browser type, and device information, collected automatically by our analytics and security providers", + "Messages you send us through the contact or review forms", + ], + }, + { + id: "2", + title: "How We Use Your Information", + points: [ + "To provide and maintain our services, including your account, dashboard, and saved progress", + "To improve user experience and service quality", + "To send important updates or respond to support emails", + "To detect and prevent spam or abuse (e.g. via Cloudflare Turnstile on login/signup)", + "To measure site performance and usage trends", + ], + }, + { + id: "3", + title: "Third-Party Services", + data: "We use the following third-party services, each of which may process data according to its own privacy policy:", + points: [ + "Supabase — authentication and database storage for accounts and progress data", + "Google Analytics — website usage analytics", + "Google AdSense — displays ads and may use cookies to personalize them based on your visits to this and other sites; you can manage ad personalization at adssettings.google.com", + "Cloudflare Turnstile — bot/spam protection on login and signup", + "Vercel — hosting and performance analytics", + ], + }, + { + id: "4", + title: "Cookies", + data: "We use cookies and similar technologies as described in our Cookie Policy, including cookies set by Google Analytics and Google AdSense. You can control cookies through your browser settings.", + }, + { + id: "5", + title: "Data Retention", + data: "We retain account and progress data for as long as your account is active. You can request deletion of your account and associated data at any time by contacting us.", + }, + { + id: "6", + title: "Children's Privacy", + data: "This website is not directed at children under the age of 13, and we do not knowingly collect personal information from children under 13. If you believe a child has provided us with personal information, please contact us so we can remove it.", + }, + { + id: "7", + title: "Your Rights", + data: "You have the right to request access, correction, or deletion of your personal data at any time by contacting us.", + }, + { + id: "8", + title: "Contact Information", + data: "For any privacy-related questions, please contact us at", + contact: "hello@dsavisualizer.in", + }, +]; + +export default function PrivacyPolicyPage() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Privacy Policy", href: "" }, + ]; + + return ( + <> +
+ +
+ +
+
+ + +
+
+ + +
+ + ); +} diff --git a/app/terms/page.jsx b/app/terms/page.jsx new file mode 100755 index 0000000..2d5b9a1 --- /dev/null +++ b/app/terms/page.jsx @@ -0,0 +1,118 @@ +import Navbar from "@/app/components/navbar"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; +import ModuleHeader from "@/app/components/modules/Header"; +import PolicyContent from "@/app/components/policy/PolicyContent"; + +export const metadata = { + title: "Terms of Service | DSA Visualizer", + description: + "Read the DSA Visualizer Terms of Service covering acceptance of terms, use license, user responsibilities, and intellectual property.", + robots: "index, follow", +}; + +const termsSections = [ + { + id: "1", + title: "Acceptance of Terms", + data: "By accessing and using this website, you accept and agree to be bound by the terms and provision of this agreement.", + }, + { + id: "2", + title: "Eligibility", + data: "You must be at least 13 years old to use this website. If you are under the age of majority in your jurisdiction, you may only use the service under the supervision of a parent or legal guardian.", + }, + { + id: "3", + title: "Use License", + points: [ + "Permission is granted to temporarily use the materials on this website for personal, non-commercial transitory viewing only", + "This is the grant of a license, not a transfer of title", + "You may not modify or copy the materials, use them for any commercial purpose, or remove any copyright or proprietary notations", + ], + }, + { + id: "4", + title: "User Accounts & Responsibilities", + points: [ + "Provide accurate and complete information when required", + "Maintain the confidentiality of your account credentials", + "Notify us immediately of any unauthorized use of your account", + "Use the service in compliance with all applicable laws and regulations", + ], + }, + { + id: "5", + title: "Termination", + data: "We may suspend or terminate your access to the service at any time, without notice, if you violate these Terms or engage in conduct we determine, in our sole discretion, to be harmful to the service or other users. You may also stop using the service and request deletion of your account at any time.", + }, + { + id: "6", + title: "Third-Party Services", + data: "The service uses third-party providers, including Supabase (authentication and data storage), Google Analytics and Google AdSense (analytics and advertising), Cloudflare Turnstile (bot protection), and Vercel (hosting). Your use of features backed by these providers is also subject to their respective terms.", + }, + { + id: "7", + title: "Intellectual Property", + data: "All content, features, and functionality on this website, including but not limited to text, graphics, logos, and software, are the exclusive property of the company and are protected by international copyright, trademark, and other intellectual property laws.", + }, + { + id: "8", + title: "Disclaimer of Warranties", + data: "This website and its content are provided \"as is\" and \"as available\" without warranties of any kind, express or implied. We do not warrant that the service will be uninterrupted, error-free, or completely secure.", + }, + { + id: "9", + title: "Limitation of Liability", + data: "In no event shall the company, nor its directors, employees, partners, agents, suppliers, or affiliates, be liable for any indirect, incidental, special, consequential or punitive damages, including without limitation, loss of profits, data, use, goodwill, or other intangible losses.", + }, + { + id: "10", + title: "Governing Law", + data: "These Terms shall be governed and construed in accordance with the laws of India, without regard to its conflict of law provisions. Any disputes arising from these Terms shall be subject to the exclusive jurisdiction of the courts of India.", + }, + { + id: "11", + title: "Changes to Terms", + data: "We reserve the right, at our sole discretion, to modify or replace these Terms at any time. By continuing to access or use our service after those revisions become effective, you agree to be bound by the revised terms.", + }, + { + id: "12", + title: "Contact Information", + data: "If you have any questions about these Terms, please contact us at", + contact: "hello@dsavisualizer.in", + }, +]; + +export default function TermsOfServicePage() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Terms of Service", href: "" }, + ]; + + return ( + <> +
+ +
+ +
+
+ + +
+
+ + +
+ + ); +} diff --git a/app/visualizer/linkedList/operations/comparison/content.jsx b/app/visualizer/linkedList/operations/comparison/content.jsx index f7edcc2..da99d47 100755 --- a/app/visualizer/linkedList/operations/comparison/content.jsx +++ b/app/visualizer/linkedList/operations/comparison/content.jsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; - +import InContentAd from "@/app/components/ads/InContentAd"; const content = () => { const [theme, setTheme] = useState("light"); @@ -24,8 +24,8 @@ const content = () => { }, []); const overview = [ - `Comparing two linked lists involves checking whether both lists contain the same sequence of values in the same order.`, - `This is typically done using a pointer approach where we traverse both lists simultaneously and compare values at each corresponding node.` + `To compare two linked lists, you're really asking one question: do both lists hold the exact same values, in the exact same order?`, + `The usual way to answer that is to walk both lists at the same time with two separate pointers, checking that the values line up at every step along the way.` ]; const mergeSteps = [ @@ -109,6 +109,8 @@ const content = () => { ))} + + diff --git a/app/visualizer/linkedList/operations/comparison/page.jsx b/app/visualizer/linkedList/operations/comparison/page.jsx index 1ee53e4..8653118 100755 --- a/app/visualizer/linkedList/operations/comparison/page.jsx +++ b/app/visualizer/linkedList/operations/comparison/page.jsx @@ -1,5 +1,8 @@ import Animation from "@/app/visualizer/linkedList/operations/comparison/animation"; import Navbar from "@/app/components/navbarinner"; +import ModuleHeader from "@/app/components/modules/Header"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; export const metadata = { title: 'Linked List Comparison Algorithm | Interactive Visualization & Step-by-Step Guide', @@ -29,10 +32,30 @@ export const metadata = { }; export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Linked List : Comparison", href: "" }, + ]; + return ( <> - - +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/app/visualizer/linkedList/operations/deletion/content.jsx b/app/visualizer/linkedList/operations/deletion/content.jsx index 9ac6553..e126039 100755 --- a/app/visualizer/linkedList/operations/deletion/content.jsx +++ b/app/visualizer/linkedList/operations/deletion/content.jsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; - +import InContentAd from "@/app/components/ads/InContentAd"; const content = () => { const [theme, setTheme] = useState("light"); @@ -24,9 +24,9 @@ const content = () => { }, []); const overview = [ - `Linked List deletion involves removing nodes from the linked data structure at various positions. Unlike arrays, linked lists allow efficient deletion at any point without requiring shifting of remaining elements.`, - `Deletion is a fundamental operation that enables dynamic modification of the list. The efficiency varies based on deletion position, from O(1) for head to O(n) for arbitrary positions or tail (without tail pointer).`, - `Proper deletion requires careful pointer manipulation to maintain list integrity and avoid memory leaks (in languages without garbage collection).`, + `Deleting from a linked list means removing a node and re-linking the nodes around it so the chain stays intact. That's the big advantage over arrays: nothing has to shift, you just point around the node you're removing.`, + `How fast that deletion is depends entirely on where the node sits. Removing the head is a constant-time O(1) fix, but reaching an arbitrary node or the tail (if you don't keep a tail pointer) means walking the list first, which costs O(n).`, + `The tricky part isn't the removal itself, it's getting the pointer rewiring right so you don't accidentally orphan part of the list or leave a dangling reference behind.`, ]; const deletionTypes = [ @@ -424,6 +424,8 @@ const content = () => {
+ + diff --git a/app/visualizer/linkedList/operations/deletion/page.jsx b/app/visualizer/linkedList/operations/deletion/page.jsx index 27bcfcf..1823f67 100755 --- a/app/visualizer/linkedList/operations/deletion/page.jsx +++ b/app/visualizer/linkedList/operations/deletion/page.jsx @@ -1,5 +1,8 @@ import Animation from "@/app/visualizer/linkedList/operations/deletion/animation"; import Navbar from "@/app/components/navbarinner"; +import ModuleHeader from "@/app/components/modules/Header"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; export const metadata = { title: 'Linked List Deletion Algorithm | Interactive Visualization & Step-by-Step Guide', @@ -29,10 +32,30 @@ export const metadata = { }; export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Linked List : Deletion", href: "" }, + ]; + return ( <> - - +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/app/visualizer/linkedList/operations/insertion/content.jsx b/app/visualizer/linkedList/operations/insertion/content.jsx index 1ef837f..1c5b4af 100755 --- a/app/visualizer/linkedList/operations/insertion/content.jsx +++ b/app/visualizer/linkedList/operations/insertion/content.jsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; - +import InContentAd from "@/app/components/ads/InContentAd"; const content = () => { const [theme, setTheme] = useState("light"); @@ -24,9 +24,9 @@ const content = () => { }, []); const overview = [ - `Linked List insertion involves adding new nodes to the linked data structure at various positions. Unlike arrays, linked lists allow efficient insertion at any point without reallocation or shifting of existing elements.`, - `Insertion is a fundamental operation that enables dynamic growth of the list. The efficiency varies based on insertion position, from O(1) for head/tail (with tail pointer) to O(n) for arbitrary positions.`, - `Mastering insertion techniques is crucial for building more complex data structures and algorithms that utilize linked lists as their foundation.`, + `Inserting into a linked list just means creating a new node and pointing the surrounding nodes at it correctly. Arrays would need to shift everything after the insertion point, but a linked list just rewires a couple of pointers.`, + `Where you insert changes the cost: adding at the head, or at the tail if you're keeping a tail pointer, is O(1). Inserting somewhere in the middle means walking the list to get there first, which is O(n).`, + `Getting comfortable with insertion is worth it early on, since it's the building block a lot of other linked-list-based structures and algorithms lean on.`, ]; const insertionTypes = [ @@ -371,6 +371,8 @@ const content = () => {

+ + diff --git a/app/visualizer/linkedList/operations/insertion/page.jsx b/app/visualizer/linkedList/operations/insertion/page.jsx index 9c9354d..cf3629e 100755 --- a/app/visualizer/linkedList/operations/insertion/page.jsx +++ b/app/visualizer/linkedList/operations/insertion/page.jsx @@ -1,5 +1,8 @@ import Animation from "@/app/visualizer/linkedList/operations/insertion/animation"; import Navbar from "@/app/components/navbarinner"; +import ModuleHeader from "@/app/components/modules/Header"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; export const metadata = { title: 'Linked List Insertion Algorithm | Interactive Visualization & Step-by-Step Guide', @@ -28,10 +31,30 @@ export const metadata = { robots: 'index, follow', }; export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Linked List : Insertion", href: "" }, + ]; + return ( <> - - +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/app/visualizer/linkedList/operations/merge/content.jsx b/app/visualizer/linkedList/operations/merge/content.jsx index 092a933..dc7e6bd 100755 --- a/app/visualizer/linkedList/operations/merge/content.jsx +++ b/app/visualizer/linkedList/operations/merge/content.jsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; - +import InContentAd from "@/app/components/ads/InContentAd"; const content = () => { const [theme, setTheme] = useState("light"); @@ -24,8 +24,8 @@ const content = () => { }, []); const overview = [ - `Merging two linked lists involves combining the nodes of both lists into one sorted list. This is typically done using a two-pointer approach where we repeatedly compare the heads of both lists and append the smaller node to the result.`, - `This operation is especially useful when both input lists are already sorted. The result is also a sorted list without requiring additional sorting operations.` + `Merging two linked lists means weaving their nodes together into a single ordered chain. The common technique is a two-pointer walk: look at both current heads, pick whichever is smaller, attach it to the result, and move that pointer forward.`, + `This trick only pays off when both lists were already sorted going in — you end up with a fully sorted merged list without ever needing to run a separate sort afterward.` ]; const mergeSteps = [ @@ -110,6 +110,8 @@ const content = () => { ))} + + diff --git a/app/visualizer/linkedList/operations/merge/page.jsx b/app/visualizer/linkedList/operations/merge/page.jsx index 18dfc2e..aab5ede 100755 --- a/app/visualizer/linkedList/operations/merge/page.jsx +++ b/app/visualizer/linkedList/operations/merge/page.jsx @@ -1,5 +1,8 @@ import Animation from "@/app/visualizer/linkedList/operations/merge/animation"; import Navbar from "@/app/components/navbarinner"; +import ModuleHeader from "@/app/components/modules/Header"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; export const metadata = { title: 'Linked List Merge Algorithm | Interactive Visualization & Step-by-Step Guide', @@ -29,10 +32,30 @@ export const metadata = { }; export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Linked List : Merge", href: "" }, + ]; + return ( <> - - +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/app/visualizer/linkedList/operations/reverse/content.jsx b/app/visualizer/linkedList/operations/reverse/content.jsx index b98e7c2..fa114c9 100755 --- a/app/visualizer/linkedList/operations/reverse/content.jsx +++ b/app/visualizer/linkedList/operations/reverse/content.jsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; - +import InContentAd from "@/app/components/ads/InContentAd"; const content = () => { const [theme, setTheme] = useState("light"); @@ -24,8 +24,8 @@ const content = () => { }, []); const overview = [ - `Reversing a linked list involves changing the direction of the pointers so that the last node becomes the head and the head becomes the last node.`, - `This operation is fundamental in many algorithms and helps in scenarios where you need to process the list in reverse order without using extra space.` + `Reversing a linked list is really just flipping every pointer so it points backward instead of forward — once that's done, what used to be the tail is now the head.`, + `It shows up constantly as a building block in other algorithms, and it's the go-to way to process a list back-to-front without allocating any extra space for a copy.` ]; const mergeSteps = [ @@ -110,6 +110,8 @@ const content = () => { ))} + + diff --git a/app/visualizer/linkedList/operations/reverse/page.jsx b/app/visualizer/linkedList/operations/reverse/page.jsx index 9be76f9..09533e5 100755 --- a/app/visualizer/linkedList/operations/reverse/page.jsx +++ b/app/visualizer/linkedList/operations/reverse/page.jsx @@ -1,5 +1,8 @@ import Animation from "@/app/visualizer/linkedList/operations/reverse/animation"; import Navbar from "@/app/components/navbarinner"; +import ModuleHeader from "@/app/components/modules/Header"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; export const metadata = { title: 'Linked List Reverse Algorithm | Interactive Visualization & Step-by-Step Guide', @@ -29,10 +32,30 @@ export const metadata = { }; export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Linked List : Reverse", href: "" }, + ]; + return ( <> - - +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +
); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/app/visualizer/linkedList/operations/traversal/content.jsx b/app/visualizer/linkedList/operations/traversal/content.jsx index 95851bc..e193b59 100755 --- a/app/visualizer/linkedList/operations/traversal/content.jsx +++ b/app/visualizer/linkedList/operations/traversal/content.jsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useState } from "react"; import NewsletterEmbed from "@/app/components/ui/NewsletterEmbed"; - +import InContentAd from "@/app/components/ads/InContentAd"; const content = () => { const [theme, setTheme] = useState("light"); @@ -24,9 +24,9 @@ const content = () => { }, []); const overview = [ - `Linked List traversal involves visiting each node in the list exactly once, starting from the head and moving through the next pointers until the end is reached.`, - `Traversal is essential for operations like searching, displaying, or processing each element of the list. It ensures that all elements are accessed in sequence.`, - `Understanding traversal is a foundational step for more advanced linked list algorithms, including deletion, reversal, and cycle detection.`, + `Traversing a linked list is simply following the chain: start at the head, visit each node once, and keep hopping to the next pointer until you hit the end.`, + `It sounds trivial, but it's the mechanism underneath almost everything else you'd do with a list — searching for a value, printing every element, or running any per-node logic all rely on visiting nodes in order.`, + `It's worth getting comfortable with early, since deletion, reversal, and cycle detection all build directly on the same idea of walking the list node by node.`, ]; const traversalTypes = [ @@ -280,6 +280,8 @@ const content = () => {
+ + diff --git a/app/visualizer/linkedList/operations/traversal/page.jsx b/app/visualizer/linkedList/operations/traversal/page.jsx index ea52d72..992277a 100755 --- a/app/visualizer/linkedList/operations/traversal/page.jsx +++ b/app/visualizer/linkedList/operations/traversal/page.jsx @@ -1,5 +1,8 @@ import Animation from "@/app/visualizer/linkedList/operations/traversal/animation"; import Navbar from "@/app/components/navbarinner"; +import ModuleHeader from "@/app/components/modules/Header"; +import Footer from "@/app/components/footer"; +import BackToTopButton from "@/app/components/ui/backtotop"; export const metadata = { title: 'Linked List Traversal Algorithm | Interactive Visualization & Step-by-Step Guide', @@ -28,10 +31,30 @@ export const metadata = { robots: 'index, follow', }; export default function Page() { + const paths = [ + { name: "Home", href: "/" }, + { name: "Visualizer", href: "/visualizer" }, + { name: "Linked List : Traversal", href: "" }, + ]; + return ( <> - - +
+ +
+ +
+
+ +
+ +
+ +
+
+ + +