From b788a4ccba7c8d88bece44075fd87f459a2a2f29 Mon Sep 17 00:00:00 2001 From: Arjun Komath Date: Tue, 30 Sep 2025 22:13:39 +1000 Subject: [PATCH 1/9] feat: Visitor authentication --- apps/page/.env.example | 2 + apps/page/components/footer.tsx | 9 +- apps/page/components/reactions.tsx | 29 ++- apps/page/components/visitor-auth-modal.tsx | 137 ++++++++++++ apps/page/components/visitor-status.tsx | 71 ++++++ apps/page/hooks/useVisitorAuth.tsx | 102 +++++++++ apps/page/lib/visitor-auth.ts | 185 ++++++++++++++++ apps/page/package.json | 1 + apps/page/pages/_app.tsx | 7 +- apps/page/pages/_sites/[site]/auth/verify.tsx | 145 ++++++++++++ .../_sites/[site]/roadmap/[roadmap_slug].tsx | 14 ++ apps/page/pages/api/auth/logout.ts | 35 +++ apps/page/pages/api/auth/me.ts | 50 +++++ .../page/pages/api/auth/request-magic-link.ts | 206 ++++++++++++++++++ apps/page/pages/api/auth/verify-magic-link.ts | 122 +++++++++++ apps/page/pages/api/pa/view.ts | 14 +- apps/page/pages/api/post/react.ts | 12 +- apps/page/pages/api/roadmap/vote.ts | 14 +- apps/page/utils/http.ts | 3 +- .../inngest/email/send-visitor-magic-link.ts | 162 ++++++++++++++ apps/web/pages/api/inngest.ts | 2 + .../migrations/19_page_visitors_auth.sql | 23 ++ packages/supabase/types/index.ts | 38 +++- packages/supabase/types/page.ts | 1 + pnpm-lock.yaml | 8 + 25 files changed, 1353 insertions(+), 39 deletions(-) create mode 100644 apps/page/components/visitor-auth-modal.tsx create mode 100644 apps/page/components/visitor-status.tsx create mode 100644 apps/page/hooks/useVisitorAuth.tsx create mode 100644 apps/page/lib/visitor-auth.ts create mode 100644 apps/page/pages/_sites/[site]/auth/verify.tsx create mode 100644 apps/page/pages/api/auth/logout.ts create mode 100644 apps/page/pages/api/auth/me.ts create mode 100644 apps/page/pages/api/auth/request-magic-link.ts create mode 100644 apps/page/pages/api/auth/verify-magic-link.ts create mode 100644 apps/web/inngest/email/send-visitor-magic-link.ts create mode 100644 packages/supabase/migrations/19_page_visitors_auth.sql diff --git a/apps/page/.env.example b/apps/page/.env.example index bc346e6..d79aaf7 100644 --- a/apps/page/.env.example +++ b/apps/page/.env.example @@ -2,6 +2,8 @@ NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_ANON_KEY= SUPABASE_SERVICE_ROLE_KEY= +VISITOR_JWT_SECRET=your-secure-secret-key-change-this-in-production + # Inngest INNGEST_EVENT_KEY= diff --git a/apps/page/components/footer.tsx b/apps/page/components/footer.tsx index 044b8a9..09a4ee7 100644 --- a/apps/page/components/footer.tsx +++ b/apps/page/components/footer.tsx @@ -1,6 +1,6 @@ +import { IPageSettings } from "@changes-page/supabase/types/page"; import Image from "next/image"; import { useEffect } from "react"; -import { IPageSettings } from "@changes-page/supabase/types/page"; import appStoreBadgeLight from "../public/badges/App_Store_Badge_US-UK_RGB_blk.svg"; import appStoreBadgeDark from "../public/badges/App_Store_Badge_US-UK_RGB_wht.svg"; import googlePlayBadge from "../public/badges/google-play-badge.png"; @@ -14,6 +14,7 @@ import { TwitterIcon, YouTubeIcon, } from "./social-icons.component"; +import VisitorStatus from "./visitor-status"; export default function Footer({ settings }: { settings: IPageSettings }) { useEffect(() => { @@ -25,8 +26,12 @@ export default function Footer({ settings }: { settings: IPageSettings }) { return (