feat: privacy policy

This commit is contained in:
Henry
2025-02-24 21:36:03 +00:00
parent 3608ec0e31
commit 08a736b210
7 changed files with 476 additions and 100 deletions

View File

@@ -25,6 +25,7 @@ export const env = createEnv({
client: {
NEXT_PUBLIC_SUPABASE_AUTH_COOKIE_NAME: z.string(),
NEXT_PUBLIC_SUPABASE_STORAGE_URL: z.string(),
NEXT_PUBLIC_UMAMI_ID: z.string().optional(),
},
/**
* Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
@@ -35,6 +36,7 @@ export const env = createEnv({
process.env.NEXT_PUBLIC_SUPABASE_AUTH_COOKIE_NAME,
NEXT_PUBLIC_SUPABASE_STORAGE_URL:
process.env.NEXT_PUBLIC_SUPABASE_STORAGE_URL,
NEXT_PUBLIC_UMAMI_ID: process.env.NEXT_PUBLIC_UMAMI_ID,
},
skipValidation:
!!process.env.CI || process.env.npm_lifecycle_event === "lint",

View File

@@ -3,6 +3,7 @@ import "~/styles/globals.css";
import type { AppType } from "next/app";
import { Plus_Jakarta_Sans } from "next/font/google";
import { env } from "~/env";
import { ModalProvider } from "~/providers/modal";
import { PopupProvider } from "~/providers/popup";
import { ThemeProvider } from "~/providers/theme";
@@ -30,6 +31,13 @@ const MyApp: AppType = ({ Component, pageProps }) => {
position: relative;
}
`}</style>
{env.NEXT_PUBLIC_UMAMI_ID && (
<script
defer
src="https://cloud.umami.is/script.js"
data-website-id={env.NEXT_PUBLIC_UMAMI_ID}
/>
)}
<main className="font-sans">
<ThemeProvider>
<ModalProvider>

View File

@@ -0,0 +1,5 @@
import PrivacyView from "~/views/privacy";
export default function Privacy() {
return <PrivacyView />;
}

View File

@@ -45,9 +45,11 @@ const Header = ({ isLoggedIn }: { isLoggedIn: boolean }) => {
>
<div className="flex w-full items-center justify-between lg:px-4">
<div className="my-auto flex items-center justify-between">
<h1 className="w-[200px] text-lg font-bold tracking-tight text-neutral-900 dark:text-dark-1000">
kan.bn
</h1>
<Link href="/">
<h1 className="w-[200px] text-lg font-bold tracking-tight text-neutral-900 dark:text-dark-1000">
kan.bn
</h1>
</Link>
</div>
{/* Desktop Menu */}
<div className="hidden justify-center gap-10 dark:text-dark-1000 lg:flex">

View File

@@ -0,0 +1,44 @@
import Cookies from "js-cookie";
import PatternedBackground from "~/components/PatternedBackground";
import { env } from "~/env";
import { useTheme } from "~/providers/theme";
import { api } from "~/utils/api";
import Footer from "./Footer";
import Header from "./Header";
export default function Layout({ children }: { children: React.ReactNode }) {
const theme = useTheme();
const token =
typeof window !== "undefined"
? Cookies.get(env.NEXT_PUBLIC_SUPABASE_AUTH_COOKIE_NAME)
: null;
const { data } = api.user.getUser.useQuery(undefined, {
enabled: !!token,
});
const isLoggedIn = !!data;
const isDarkMode = theme.activeTheme === "dark";
return (
<>
<style jsx global>{`
html {
scroll-behavior: smooth;
background-color: ${!isDarkMode ? "hsl(0deg 0% 97.3%)" : "#161616"};
}
`}</style>
<div className="mx-auto flex h-full min-h-screen min-w-[375px] flex-col items-center bg-light-100 dark:bg-dark-50">
<PatternedBackground />
<div className="z-10 mx-auto h-full w-full max-w-[1100px]">
<Header isLoggedIn={isLoggedIn} />
{children}
</div>
<Footer />
</div>
</>
);
}

View File

@@ -1,122 +1,92 @@
import Image from "next/image";
import Link from "next/link";
import Cookies from "js-cookie";
import { IoLogoGithub } from "react-icons/io";
import Button from "~/components/Button";
import PatternedBackground from "~/components/PatternedBackground";
import { env } from "~/env";
import { useTheme } from "~/providers/theme";
import { api } from "~/utils/api";
import Cta from "./components/Cta";
import FAQs from "./components/Faqs";
import Features from "./components/Features";
import Footer from "./components/Footer";
import Header from "./components/Header";
import Layout from "./components/Layout";
import Pricing from "./components/Pricing";
export default function HomeView() {
const theme = useTheme();
const token =
typeof window !== "undefined"
? Cookies.get(env.NEXT_PUBLIC_SUPABASE_AUTH_COOKIE_NAME)
: null;
const { data } = api.user.getUser.useQuery(undefined, {
enabled: !!token,
});
const isLoggedIn = !!data;
const isDarkMode = theme.activeTheme === "dark";
return (
<>
<style jsx global>{`
html {
scroll-behavior: smooth;
background-color: ${!isDarkMode ? "hsl(0deg 0% 97.3%)" : "#161616"};
}
`}</style>
<div className="mx-auto flex h-full min-h-screen min-w-[375px] flex-col items-center bg-light-100 dark:bg-dark-50">
<PatternedBackground />
<div className="z-10 mx-auto h-full w-full max-w-[1100px]">
<Header isLoggedIn={isLoggedIn} />
<div className="flex h-full w-full flex-col lg:pt-[5rem]">
<div className="w-full pb-10 pt-32 lg:py-32">
<div className="animate-fade-down my-10 flex h-full w-full flex-col items-center justify-center px-4">
<div className="animate-fade-in relative overflow-hidden rounded-full bg-gradient-to-b from-light-300 to-light-400 p-[2px] dark:from-dark-300 dark:to-dark-400">
<div className="gradient-border absolute inset-0 animate-border-spin" />
<div className="relative z-10 rounded-full bg-light-50 dark:bg-dark-50">
<Link
href="https://github.com/kanbn/kan"
rel="noopener noreferrer"
target="_blank"
className="flex items-center gap-2 px-4 py-1 text-center text-xs text-light-1000 dark:text-dark-1000 lg:text-sm"
>
Star on Github
<IoLogoGithub size={20} />
</Link>
</div>
</div>
<p className="mt-2 text-center text-4xl font-bold text-light-1000 dark:text-dark-1000 lg:text-5xl">
The open source <br />
alternative to Trello
</p>
<p className="text-md mt-3 max-w-[450px] text-center text-dark-900 lg:max-w-[600px] lg:text-lg">
A powerful, flexible kanban app that helps you organise work,
track progress, and deliver resultsall in one place.
</p>
<div className="mt-6 flex gap-2">
<Button href="/signup">Get started on Cloud</Button>
<Button
variant="secondary"
href="https://github.com/kanbn/kan"
openInNewTab
>
Self host with Github
</Button>
</div>
<p className="mt-4 text-center text-sm text-dark-900">
No credit card required
</p>
<Layout>
<div className="flex h-full w-full flex-col lg:pt-[5rem]">
<div className="w-full pb-10 pt-32 lg:py-32">
<div className="my-10 flex h-full w-full animate-fade-down flex-col items-center justify-center px-4">
<div className="relative animate-fade-in overflow-hidden rounded-full bg-gradient-to-b from-light-300 to-light-400 p-[2px] dark:from-dark-300 dark:to-dark-400">
<div className="gradient-border absolute inset-0 animate-border-spin" />
<div className="relative z-10 rounded-full bg-light-50 dark:bg-dark-50">
<Link
href="https://github.com/kanbn/kan"
rel="noopener noreferrer"
target="_blank"
className="flex items-center gap-2 px-4 py-1 text-center text-xs text-light-1000 dark:text-dark-1000 lg:text-sm"
>
Star on Github
<IoLogoGithub size={20} />
</Link>
</div>
</div>
<div className="px-4">
<div className="mb-24 rounded-[16px] border border-light-300 bg-light-50 p-1 shadow-md dark:border-dark-300 dark:bg-dark-100 lg:rounded-[24px] lg:p-2">
<div className="overflow-hidden rounded-[12px] border border-light-300 shadow-sm dark:border-dark-300 lg:rounded-[16px]">
<Image
src={`/hero-${isDarkMode ? "dark" : "light"}.png`}
alt="kanban"
width={1100}
height={1000}
/>
</div>
</div>
<p className="mt-2 text-center text-4xl font-bold text-light-1000 dark:text-dark-1000 lg:text-5xl">
The open source <br />
alternative to Trello
</p>
<p className="text-md mt-3 max-w-[450px] text-center text-dark-900 lg:max-w-[600px] lg:text-lg">
A powerful, flexible kanban app that helps you organise work,
track progress, and deliver resultsall in one place.
</p>
<div className="mt-6 flex gap-2">
<Button href="/signup">Get started on Cloud</Button>
<Button
variant="secondary"
href="https://github.com/kanbn/kan"
openInNewTab
>
Self host with Github
</Button>
</div>
<div className="relative pt-10">
<div id="features" className="absolute -top-20" />
<Features theme={theme.activeTheme} />
</div>
<div className="relative pt-10">
<div id="pricing" className="absolute -top-20" />
<Pricing />
</div>
<div className="relative pt-10">
<div id="faq" className="absolute -top-20" />
<FAQs />
</div>
<div className="relative">
<Cta theme={theme.activeTheme} />
<p className="mt-4 text-center text-sm text-dark-900">
No credit card required
</p>
</div>
</div>
<div className="px-4">
<div className="mb-24 rounded-[16px] border border-light-300 bg-light-50 p-1 shadow-md dark:border-dark-300 dark:bg-dark-100 lg:rounded-[24px] lg:p-2">
<div className="overflow-hidden rounded-[12px] border border-light-300 shadow-sm dark:border-dark-300 lg:rounded-[16px]">
<Image
src={`/hero-${isDarkMode ? "dark" : "light"}.png`}
alt="kanban"
width={1100}
height={1000}
/>
</div>
</div>
</div>
<Footer />
<div className="relative pt-10">
<div id="features" className="absolute -top-20" />
<Features theme={theme.activeTheme} />
</div>
<div className="relative pt-10">
<div id="pricing" className="absolute -top-20" />
<Pricing />
</div>
<div className="relative pt-10">
<div id="faq" className="absolute -top-20" />
<FAQs />
</div>
<div className="relative">
<Cta theme={theme.activeTheme} />
</div>
</div>
</>
</Layout>
);
}

View File

@@ -0,0 +1,345 @@
import Link from "next/link";
import Layout from "../home/components/Layout";
export default function PrivacyView() {
const SubHeading = ({ children }: { children: React.ReactNode }) => (
<h3 className="mb-4 text-2xl font-bold text-light-1000 dark:text-dark-950">
{children}
</h3>
);
const Text = ({ children }: { children: React.ReactNode }) => (
<p className="line-height text-md mb-4 text-light-1000 dark:text-dark-900">
{children}
</p>
);
const UnorderedList = ({ children }: { children: React.ReactNode }) => (
<ul className="list-disc pl-6">{children}</ul>
);
const ListItem = ({ children }: { children: React.ReactNode }) => (
<li className="line-height text-md mb-4 text-light-1000 dark:text-dark-900">
{children}
</li>
);
const NAME = "Kan.bn";
return (
<Layout>
<div className="flex flex-col items-center">
<div className="mb-20 flex h-full w-full max-w-[800px] flex-col lg:pt-[5rem]">
<div className="flex items-center justify-center py-36 text-4xl font-bold tracking-tight text-light-1000 dark:text-dark-1000">
<h2>Privacy Policy</h2>
</div>
<p className="mb-6 text-sm text-light-1000 dark:text-dark-900">
Last updated: 23rd Feb 2025
</p>
<div className="mb-6">
<SubHeading>Introduction</SubHeading>
<Text>
Your privacy is important to us. It is our policy to respect your
privacy and comply with any applicable law and regulation
regarding any personal information we may collect about you,
including across our website, {NAME}, and other sites we own and
operate.
</Text>
</div>
<div className="mb-6">
<SubHeading>Information We Collect</SubHeading>
<Text>
Information we collect includes both information you knowingly and
actively provide us when using or participating in any of our
services and promotions, and any information automatically sent by
your devices in the course of accessing our products and services.
</Text>
</div>
<div className="mb-6">
<SubHeading>Log Data</SubHeading>
<Text>
When you visit our website, our servers may automatically log the
standard data provided by your web browser. It may include your
devices Internet Protocol (IP) address, your browser type and
version, the pages you visit, the time and date of your visit, the
time spent on each page, other details about your visit, and
technical details that occur in conjunction with any errors you
may encounter.
</Text>
<Text>
Please be aware that while this information may not be personally
identifying by itself, it may be possible to combine it with other
data to personally identify individual persons.
</Text>
</div>
<div className="mb-6">
<SubHeading>Personal Information</SubHeading>
<Text>
We may ask for personal information which may include one or more
of the following:
</Text>
<UnorderedList>
<ListItem>Name</ListItem>
<ListItem>Email</ListItem>
</UnorderedList>
</div>
<div className="mb-6">
<SubHeading>
Legitimate Reasons for Processing Your Personal Information
</SubHeading>
<Text>
We only collect and use your personal information when we have a
legitimate reason for doing so. In which instance, we only collect
personal information that is reasonably necessary to provide our
services to you.
</Text>
</div>
<div className="mb-6">
<SubHeading>Collection and Use of Information</SubHeading>
<Text>
We may collect personal information from you when you do any of
the following on our website:
</Text>
<UnorderedList>
<ListItem>
Sign up to receive updates from us via email or social media
channels
</ListItem>
<ListItem>
Use a mobile device or web browser to access our content
</ListItem>
<ListItem>
Contact us via email, social media, or on any similar
technologies
</ListItem>
<ListItem>When you mention us on social media</ListItem>
</UnorderedList>
<Text>
We may collect, hold, use, and disclose information for the
following purposes, and personal information will not be further
processed in a manner that is incompatible with these purposes:
</Text>
<UnorderedList>
<ListItem>to contact and communicate with you</ListItem>
<ListItem>
for analytics, market research, and business development,
including to operate and improve our website, associated
applications, and associated social media platforms
</ListItem>
<ListItem>
to enable you to access and use our website, associated
applications, and associated social media platforms
</ListItem>
</UnorderedList>
<Text>
Please be aware that we may combine information we collect about
you with general information or research data we receive from
other trusted sources.
</Text>
</div>
<div className="mb-6">
<SubHeading>Security of Your Personal Information</SubHeading>
<Text>
When we collect and process personal information, and while we
retain this information, we will protect it within commercially
acceptable means to prevent loss and theft, as well as
unauthorized access, disclosure, copying, use, or modification.
</Text>
<Text>
Although we will do our best to protect the personal information
you provide to us, we advise that no method of electronic
transmission or storage is 100% secure, and no one can guarantee
absolute data security. We will comply with laws applicable to us
in respect of any data breach.
</Text>
<Text>
You are responsible for selecting any password and its overall
security strength, ensuring the security of your own information
within the bounds of our services.
</Text>
</div>
<div className="mb-6">
<SubHeading>How Long We Keep Your Personal Information</SubHeading>
<Text>
We keep your personal information only for as long as we need to.
This time period may depend on what we are using your information
for, in accordance with this privacy policy. If your personal
information is no longer required, we will delete it or make it
anonymous by removing all details that identify you.
</Text>
<Text>
However, if necessary, we may retain your personal information for
our compliance with a legal, accounting, or reporting obligation
or for archiving purposes in the public interest, scientific, or
historical research purposes or statistical purposes.
</Text>
</div>
<div className="mb-6">
<SubHeading>Childrens Privacy</SubHeading>
<Text>
We do not aim any of our products or services directly at children
under the age of 13, and we do not knowingly collect personal
information about children under 13.
</Text>
</div>
<div className="mb-6">
<SubHeading>
Disclosure of Personal Information to Third Parties
</SubHeading>
<Text>We may disclose personal information to</Text>
<UnorderedList>
<ListItem>
a parent, subsidiary, or affiliate of our company
</ListItem>
<ListItem>
third party service providers for the purpose of enabling them
to provide their services, for example, IT service providers,
data storage, hosting and server providers, advertisers, or
analytics platforms
</ListItem>
<ListItem>
our employees, contractors, and/or related entities
</ListItem>
<ListItem>
our existing or potential agents or business partners
</ListItem>
<ListItem>
sponsors or promoters of any competition, sweepstakes, or
promotion we run
</ListItem>
<ListItem>
courts, tribunals, regulatory authorities, and law enforcement
officers, as required by law, in connection with any actual or
prospective legal proceedings, or in order to establish,
exercise, or defend our legal rights
</ListItem>
<ListItem>
third parties, including agents or sub-contractors, who assist
us in providing information, products, services, or direct
marketing to you third parties to collect and process data
</ListItem>
</UnorderedList>
</div>
<div className="mb-6">
<SubHeading>
International Transfers of Personal Information
</SubHeading>
<Text>
The personal information we collect is stored and/or processed
where we or our partners, affiliates, and third-party providers
maintain facilities. Please be aware that the locations to which
we store, process, or transfer your personal information may not
have the same data protection laws as the country in which you
initially provided the information. If we transfer your personal
information to third parties in other countries: (i) we will
perform those transfers in accordance with the requirements of
applicable law; and (ii) we will protect the transferred personal
information in accordance with this privacy policy.
</Text>
</div>
<div className="mb-6">
<SubHeading>
Your Rights and Controlling Your Personal Information
</SubHeading>
<Text>
You always retain the right to withhold personal information from
us, with the understanding that your experience of our website may
be affected. We will not discriminate against you for exercising
any of your rights over your personal information. If you do
provide us with personal information you understand that we will
collect, hold, use and disclose it in accordance with this privacy
policy. You retain the right to request details of any personal
information we hold about you.
</Text>
<Text>
If we receive personal information about you from a third party,
we will protect it as set out in this privacy policy. If you are a
third party providing personal information about somebody else,
you represent and warrant that you have such persons consent to
provide the personal information to us.
</Text>
<Text>
If you have previously agreed to us using your personal
information for direct marketing purposes, you may change your
mind at any time. We will provide you with the ability to
unsubscribe from our email-database or opt out of communications.
Please be aware we may need to request specific information from
you to help us confirm your identity.
</Text>
<Text>
If you believe that any information we hold about you is
inaccurate, out of date, incomplete, irrelevant, or misleading,
please contact us using the details provided in this privacy
policy. We will take reasonable steps to correct any information
found to be inaccurate, incomplete, misleading, or out of date.
</Text>
<Text>
If you believe that we have breached a relevant data protection
law and wish to make a complaint, please contact us using the
details below and provide us with full details of the alleged
breach. We will promptly investigate your complaint and respond to
you, in writing, setting out the outcome of our investigation and
the steps we will take to deal with your complaint. You also have
the right to contact a regulatory body or data protection
authority in relation to your complaint.
</Text>
</div>
<div className="mb-6">
<SubHeading>Limits of Our Policy</SubHeading>
<Text>
Our website may link to external sites that are not operated by
us. Please be aware that we have no control over the content and
policies of those sites, and cannot accept responsibility or
liability for their respective privacy practices.
</Text>
</div>
<div className="mb-6">
<SubHeading>Changes to This Policy</SubHeading>
<Text>
At our discretion, we may change our privacy policy to reflect
updates to our business processes, current acceptable practices,
or legislative or regulatory changes. If we decide to change this
privacy policy, we will post the changes here at the same link by
which you are accessing this privacy policy.
</Text>
<Text>
If required by law, we will get your permission or give you the
opportunity to opt in to or opt out of, as applicable, any new
uses of your personal information.
</Text>
</div>
<div className="mb-6">
<SubHeading>Contact Us</SubHeading>
<Text>
For any questions or concerns regarding your privacy, you may
contact us using the following details:
</Text>
<Link
className="line-height text-md mb-4 text-light-1000 dark:text-dark-900"
href="mailto:support@kan.bn"
>
support@kan.bn
</Link>
</div>
</div>
</div>
</Layout>
);
}