forked from Mike/freno-dev
nessa.freno.me/terms was a live 404 although AppSettings.termsOfServiceURL links it from Settings > Legal and the paywall. The document existed only on an unmerged branch and had no host-dispatch route, so it could not serve on the subdomain. Carry the Terms of Use page, add the /terms dispatcher, and publish nessa-support@freno.me on terms, privacy, contact and deletion. - src/routes/terms.tsx: host-aware dispatch for nessa; other sites 404. - src/routes/nessa/terms.tsx: the Terms page; its contact section names the support address. - privacy: add the controller clause and the support address. - contact/deletion: show the support address; deletion also accepts a request by email. - subdomain-dispatch.test.ts: list directories before filtering to .tsx files. The old predicate only ever received file names, so it asserted over an empty list and missed the missing /terms dispatch. - support-contact.test.ts: guard that every contact route renders the one address the app shows. App side unchanged: termsOfServiceURL stays https://nessa.freno.me/terms.
79 lines
3.2 KiB
TypeScript
79 lines
3.2 KiB
TypeScript
/**
|
|
* Nessa per-subdomain account-deletion page — `nessa.freno.me/deletion`
|
|
* (see `./deletion-content.ts`).
|
|
*
|
|
* Served at the public browser path `/deletion` (vercel.json host rewrites
|
|
* `nessa.freno.me/*` → the internal `/nessa/*` route prefix, leaving the
|
|
* browser URL clean.
|
|
*
|
|
* Nessa deletion assessment (see `./deletion-content.ts` for the full
|
|
* rationale): Nessa stores user data (`users`, `workouts`, `workoutPlans`,
|
|
* `exerciseLibrary`, community memberships) in a per-user Turso DB +
|
|
* shared community tables, authenticated via Clerk. → A deletion flow IS
|
|
* needed; this page provides it via the same email-request pattern Lineage
|
|
* uses, reusing the shared `DeletionForm` with `product="nessa"` so the
|
|
* generalized `misc.sendDeletionRequestEmail` mutation sends Nessa-branded
|
|
* email + writes a Nessa-specific cooldown cookie.
|
|
*
|
|
* Auth: NO freno.me web-auth — Nessa authenticates via Clerk; the deletion
|
|
* request is email-based (the requester may be locked out of their Clerk
|
|
* session), NOT an authenticated self-delete. The nav-config does NOT list
|
|
* a Nessa deletion link by default, so this page is reachable by direct URL
|
|
* + from the Nessa privacy policy.
|
|
*
|
|
* Acceptance: `nessa.localhost:3000/deletion` renders the deletion form.
|
|
*/
|
|
import { PageHead } from "~/components/PageHead";
|
|
import { EdgeCacheHeaders } from "~/components/EdgeCacheHeaders";
|
|
import SubdomainHeader from "~/components/SubdomainHeader";
|
|
import DeletionForm from "~/components/DeletionForm";
|
|
import {
|
|
DELETION_PRODUCT_KEY,
|
|
DELETION_COOKIE_NAME,
|
|
DELETION_GRACE_PERIOD_LABEL,
|
|
PAGE_META
|
|
} from "~/routes/nessa/deletion-content";
|
|
import { SUPPORT_EMAIL } from "./content";
|
|
|
|
export default function NessaDeletionPage() {
|
|
return (
|
|
<>
|
|
<EdgeCacheHeaders maxAge={300} />
|
|
<PageHead title={PAGE_META.title} description={PAGE_META.description} />
|
|
<SubdomainHeader />
|
|
<div class="pt-20">
|
|
<div class="mx-auto p-4 md:p-6 lg:p-12">
|
|
<div class="text-text w-full justify-center">
|
|
<div class="text-xl">
|
|
<em>What will happen</em>:
|
|
</div>
|
|
Once you send, if a match to the email provided is found in our
|
|
system, a {DELETION_GRACE_PERIOD_LABEL} grace period is started
|
|
where you can request a cancellation of the account deletion. Once
|
|
the grace period ends, your Nessa account entry, your workout and
|
|
plan data, and your community memberships will be completely
|
|
removed. No data related to the account is retained in any way.
|
|
</div>
|
|
|
|
<div class="text-text mt-4 w-full justify-center">
|
|
Prefer email? Send your deletion request from the address on your
|
|
Nessa account to{" "}
|
|
<a
|
|
href={`mailto:${SUPPORT_EMAIL}?subject=Account%20Deletion%20Request`}
|
|
class="text-blue hover-underline-animation"
|
|
>
|
|
{SUPPORT_EMAIL}
|
|
</a>
|
|
; the same {DELETION_GRACE_PERIOD_LABEL} grace period applies.
|
|
</div>
|
|
|
|
<DeletionForm
|
|
product={DELETION_PRODUCT_KEY}
|
|
cookieName={DELETION_COOKIE_NAME}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|