diff --git a/src/App.tsx b/src/App.tsx index 7680828..a224bd4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,6 @@ import { Route } from "@solidjs/router"; import { type Component } from "solid-js"; -import { DmId, GroupId, Home, Overview, preloadDmId } from "./pages"; +import { DmId, GroupId, Home, Overview, preloadDmId, Privacy } from "./pages"; import "./app.css"; @@ -11,6 +11,7 @@ const App: Component = () => { + ); }; diff --git a/src/components/ui/A.tsx b/src/components/ui/A.tsx index 6ab6450..c4f9180 100644 --- a/src/components/ui/A.tsx +++ b/src/components/ui/A.tsx @@ -4,5 +4,5 @@ import clsx from "clsx"; export const A: Component = (props) => { const [local, other] = splitProps(props, ["class"]); - return ; + return ; }; diff --git a/src/index.tsx b/src/index.tsx index 337c61c..7425a2a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -17,6 +17,8 @@ if (import.meta.env.DEV && !(root instanceof HTMLElement)) { ); } +const NO_DATA_NEEDED_PAGES = ["/", "/privacy"]; + if (root) { render( () => ( @@ -27,7 +29,7 @@ if (root) { const navigate = useNavigate(); createEffect(() => { - if (!dbLoaded() && !hasCashedData() && props.location.pathname !== "/") { + if (!dbLoaded() && !hasCashedData() && !NO_DATA_NEEDED_PAGES.includes(props.location.pathname)) { navigate("/"); } }); diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 37439ba..6618102 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,6 +1,7 @@ import { lazy } from "solid-js"; export { Home } from "./home"; +export { Privacy } from "./privacy"; export { preloadDmId } from "./dm/dm-id"; export const GroupId = lazy(() => import("./group/group-id")); diff --git a/src/pages/privacy.tsx b/src/pages/privacy.tsx new file mode 100644 index 0000000..a73a67b --- /dev/null +++ b/src/pages/privacy.tsx @@ -0,0 +1,97 @@ +import type { RouteSectionProps } from "@solidjs/router"; +import type { Component } from "solid-js"; +import { A } from "~/components/ui/A"; +import { Heading } from "~/components/ui/heading"; + +export const Privacy: Component = () => { + return ( +
+ Privacy policy + Introduction +

+ This project ("signalstats", "I", "my") was built with the explicit target to not harm the privacy of its users. + This project was created to be useful, but also to showcase privacy preserving technology. It is built to not + collect any personal identifiable information. +

+

+ Therefore all data processing happens on your device. The data contained in your backup and your passphrase will + never leave it. +

+ Data I collect and usage of data +

+ I do not track any individual people. When you visit my website, your browser transfers data to the server, + which makes you identifiable like your IP address. This is just how browsers work. But I do not use that data to + track you or try to identify you as a person. +

+

+ To ensure that signalstats keeps working, the server logs some information that helps with identifying problems. +
+ My server logs the following information: +

+
    +
  • + The date and time of the request: day/month/year:time timezone offset +
  • +
  • + The type of the request, for example GET or POST, and which version of the + HTTP protocol was used, for example HTTP/2.0 +
  • +
  • + The status code of the request (for example if it was successful or not): 200 +
  • +
  • + The referer URL, meaning from which site you came:{" "} + https://git.duskflower.dev/duskflower/signal-stats +
  • +
  • + The user agent, which contains information about your system and browser:{" "} + Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0 +
  • +
+

+ The server on purpose does not log the IP address. +

+

+ These logs are kept for 10 days after which they are permanently deleted. +
I use a self-hosted instance of Umami to collect anonymous statistics about + my website. The goal is to stay up to date with the website traffic and identify trends in it. The collected + data does not allow us to identify individuals. All of it is stored in aggregated form. The raw data is + immediately deleted after the statistics are generated. That means that if I collect your screen resolution, it + will only be used to detect the type of device (desktop, laptop, mobile), and the IP address is only used to + identify the country you are coming from. +

+ Sharing of data with third parties +

+ I do not in any way share data with advertising companies or other third parties. Everything runs on my own + server. +
+ The only situation in which I might need to share data is to comply with legal requirements. +

+ Your rights +

You have certain rights regarding your personal data:

+
    +
  • The right to access your data
  • +
  • The right to rectify your data
  • +
  • The right to request deletion of your data
  • +
+

However, since I am not processing any personal data,

+ Contact +

+ I run this website as an individual. If you have any questions or complaints regarding my privacy and data + practices, you can reach out to the data controller: +

+

+ Duskflower Technologies +
+ privacy(at)duskflower.dev +

+ About this policy +

+ This policy is currently up to date, the last change was done in January 2024. +
+ With the development of signalstats or with new legal requirements it might become necessary to adjust the + policy. All updates will be posted under here. To get the current version, refer to this page. +

+
+ ); +};