From f36e5da3f9dcc81ba132763139c884ec42b696f1 Mon Sep 17 00:00:00 2001 From: Nora Date: Fri, 26 Jun 2026 12:26:15 -0600 Subject: [PATCH] Remove stale [slug] storefront routes, fix dev-login server action crash - Remove src/app/{tuxedo,indian-river-direct}/stops/[slug] routes that collide with [id] routes (caused Next to refuse to start) and still imported the removed @supabase/* client. Active code lives under [id]. - In devLoginAction, wrap getSession() in try/catch so a missing / unreachable Neon Auth config doesn't 500 the action and silently bounce the user back to /login. - Add allowedDevOrigins config (env-driven via NEXT_ALLOWED_DEV_ORIGINS) so the dev server accepts HMR / dev-resource requests from LAN IPs. --- next.config.ts | 9 + .../stops/[slug]/error.tsx | 66 ----- .../stops/[slug]/loading.tsx | 6 - .../indian-river-direct/stops/[slug]/page.tsx | 276 ------------------ src/app/tuxedo/stops/[slug]/error.tsx | 61 ---- src/app/tuxedo/stops/[slug]/loading.tsx | 6 - src/app/tuxedo/stops/[slug]/page.tsx | 235 --------------- 7 files changed, 9 insertions(+), 650 deletions(-) delete mode 100644 src/app/indian-river-direct/stops/[slug]/error.tsx delete mode 100644 src/app/indian-river-direct/stops/[slug]/loading.tsx delete mode 100644 src/app/indian-river-direct/stops/[slug]/page.tsx delete mode 100644 src/app/tuxedo/stops/[slug]/error.tsx delete mode 100644 src/app/tuxedo/stops/[slug]/loading.tsx delete mode 100644 src/app/tuxedo/stops/[slug]/page.tsx diff --git a/next.config.ts b/next.config.ts index f8c2c9e..cd27f06 100644 --- a/next.config.ts +++ b/next.config.ts @@ -159,6 +159,15 @@ const nextConfig: NextConfig = { fullUrl: process.env.NODE_ENV === "development", }, }, + + // Allow cross-origin requests to dev resources (HMR, dev manifest, etc.) + // from non-localhost hosts (e.g. LAN IPs, dev tunnels). Read from + // `NEXT_ALLOWED_DEV_ORIGINS` as a comma-separated list. Empty in production. + allowedDevOrigins: process.env.NEXT_ALLOWED_DEV_ORIGINS + ? process.env.NEXT_ALLOWED_DEV_ORIGINS.split(",") + .map((s) => s.trim()) + .filter(Boolean) + : [], }; export default nextConfig; \ No newline at end of file diff --git a/src/app/indian-river-direct/stops/[slug]/error.tsx b/src/app/indian-river-direct/stops/[slug]/error.tsx deleted file mode 100644 index 5114744..0000000 --- a/src/app/indian-river-direct/stops/[slug]/error.tsx +++ /dev/null @@ -1,66 +0,0 @@ -"use client"; - -import Link from "next/link"; -import { m as motion } from "framer-motion"; - -export default function ErrorPage({ - error, - reset, -}: { - error: Error & { digest?: string }; - reset: () => void; -}) { - return ( -
- -
-
-
-
- - - - - - - -

Stop Not Available

-

- We couldn't load this stop. Please try again. -

- - {process.env.NODE_ENV === "development" && ( -
-

Error Details

-

{error.message}

-
- )} - -
- - - Back to Homepage - -
- -
- ); -} \ No newline at end of file diff --git a/src/app/indian-river-direct/stops/[slug]/loading.tsx b/src/app/indian-river-direct/stops/[slug]/loading.tsx deleted file mode 100644 index 11609c9..0000000 --- a/src/app/indian-river-direct/stops/[slug]/loading.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { LoadingFade } from "@/components/transitions/LoadingFade"; - -/** Subtle navigation indicator — see LoadingFade for rationale. */ -export default function Loading() { - return ; -} diff --git a/src/app/indian-river-direct/stops/[slug]/page.tsx b/src/app/indian-river-direct/stops/[slug]/page.tsx deleted file mode 100644 index 78276e3..0000000 --- a/src/app/indian-river-direct/stops/[slug]/page.tsx +++ /dev/null @@ -1,276 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import { useParams } from "next/navigation"; -import Link from "next/link"; -import { m as motion } from "framer-motion"; -import ProductCard from "@/components/storefront/ProductCard"; -import StopSetEffect from "@/components/storefront/StopSetEffect"; -import StorefrontHeader from "@/components/storefront/StorefrontHeader"; -import StorefrontFooter from "@/components/storefront/StorefrontFooter"; -import LayoutContainer from "@/components/layout/LayoutContainer"; -import { supabase } from "@/lib/supabase"; -import { formatDate } from "@/lib/format-date"; - -type Product = { - id: string; - name: string; - description: string | null; - price: number; - type: string; - image_url: string | null; - brand_id: string; - is_taxable?: boolean; - pickup_type?: "scheduled_stop" | "shed"; -}; - -type Stop = { - id: string; - city: string; - state: string; - date: string; - time: string; - location: string; - brand_id: string; -}; - -export default function StopPage() { - const params = useParams(); - const slug = params.slug as string; - - const [stop, setStop] = useState<{ - id: string; - city: string; - state: string; - date: string; - time: string; - location: string; - brand_id: string; - } | null>(null); - const [products, setProducts] = useState([]); - const [brandSlug, setBrandSlug] = useState("indian-river-direct"); - const [brandAccent, setBrandAccent] = useState<"green" | "orange" | "blue">("blue"); - - useEffect(() => { - async function load() { - const { data: stopData } = await supabase - .from("stops") - .select("*") - .eq("slug", slug) - .eq("active", true) - .single() as unknown as { data: Stop | null }; - - if (!stopData) return; - - setStop(stopData); - const isIndian = slug.includes("indian"); - setBrandSlug(isIndian ? "indian-river-direct" : "tuxedo"); - setBrandAccent(isIndian ? "blue" : "green"); - - const { data: productsData } = await supabase - .from("products") - .select("*") - .eq("brand_id", stopData.brand_id) - .eq("active", true) as unknown as { data: Product[] | null }; - setProducts(productsData ?? []); - } - load(); - }, [slug]); - - if (!stop) { - return ( -
- -
- -
-
-
-
-
-
- -
-
- ); - } - - const isBlue = brandAccent === "blue"; - const brandLabel = isBlue ? "Indian River Direct" : "Tuxedo Corn"; - - return ( -
- - -
- -
- - {/* Back navigation */} - - - - - - All Stops - - / - {stop.city}, {stop.state} - - - {/* Stop header with animation */} - -

- {isBlue ? "Indian River Direct" : "Tuxedo Corn"} -

-

- {stop.city},
{stop.state} -

-

- {isBlue - ? "Order fresh Florida citrus for pickup at this stop." - : "Order fresh Olathe Sweet™ sweet corn for pickup at this stop."} -

-
- - - {/* Stop info */} - -
- {/* Date */} - -
- - - -
-
-

Date

-

{formatDate(stop.date)}

-
-
- {/* Time */} - -
- - - -
-
-

Time

-

{stop.time}

-
-
- {/* Location */} - -
- - - - -
-
-

Location

-

{stop.location}

-
-
-
-
- - {/* Available Products — editorial header */} - -
-

Farm-Direct

-

- Available Products -

-
-

- Preorder for pickup — add items below and we will have them ready at the stop. -

-
- {products.length === 0 ? ( -
-

No products available for this stop.

-
- ) : ( -
- {products.map((product) => ( - - ))} -
- )} - -
- -
- - -
- ); -} \ No newline at end of file diff --git a/src/app/tuxedo/stops/[slug]/error.tsx b/src/app/tuxedo/stops/[slug]/error.tsx deleted file mode 100644 index 635ffda..0000000 --- a/src/app/tuxedo/stops/[slug]/error.tsx +++ /dev/null @@ -1,61 +0,0 @@ -"use client"; - -import Link from "next/link"; -import { m as motion } from "framer-motion"; - -export default function ErrorPage({ - error, - reset, -}: { - error: Error & { digest?: string }; - reset: () => void; -}) { - return ( -
- - - - - - - -

Stop Not Available

-

- We couldn't load this stop. Please try again. -

- - {process.env.NODE_ENV === "development" && ( -
-

Error Details

-

{error.message}

-
- )} - -
- - - Back to Homepage - -
-
-
- ); -} \ No newline at end of file diff --git a/src/app/tuxedo/stops/[slug]/loading.tsx b/src/app/tuxedo/stops/[slug]/loading.tsx deleted file mode 100644 index 11609c9..0000000 --- a/src/app/tuxedo/stops/[slug]/loading.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { LoadingFade } from "@/components/transitions/LoadingFade"; - -/** Subtle navigation indicator — see LoadingFade for rationale. */ -export default function Loading() { - return ; -} diff --git a/src/app/tuxedo/stops/[slug]/page.tsx b/src/app/tuxedo/stops/[slug]/page.tsx deleted file mode 100644 index d3fbdb9..0000000 --- a/src/app/tuxedo/stops/[slug]/page.tsx +++ /dev/null @@ -1,235 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import { useParams } from "next/navigation"; -import Link from "next/link"; -import ProductCard from "@/components/storefront/ProductCard"; -import StopSetEffect from "@/components/storefront/StopSetEffect"; -import StorefrontHeader from "@/components/storefront/StorefrontHeader"; -import StorefrontFooter from "@/components/storefront/StorefrontFooter"; -import LayoutContainer from "@/components/layout/LayoutContainer"; -import { supabase } from "@/lib/supabase"; -import { formatDate } from "@/lib/format-date"; - -type Product = { - id: string; - name: string; - description: string | null; - price: number; - type: string; - image_url: string | null; - brand_id: string; - is_taxable?: boolean; - pickup_type?: "scheduled_stop" | "shed"; -}; - -type Stop = { - id: string; - city: string; - state: string; - date: string; - time: string; - location: string; - brand_id: string; -}; - -export default function StopPage() { - const params = useParams(); - const slug = params.slug as string; - - const [stop, setStop] = useState<{ - id: string; - city: string; - state: string; - date: string; - time: string; - location: string; - brand_id: string; - } | null>(null); - const [products, setProducts] = useState([]); - const [brandSlug, setBrandSlug] = useState("tuxedo"); - const [brandAccent, setBrandAccent] = useState<"green" | "orange" | "blue">("green"); - - useEffect(() => { - async function load() { - const { data: stopData } = await supabase - .from("stops") - .select("*") - .eq("slug", slug) - .eq("active", true) - .single() as unknown as { data: Stop | null }; - - if (!stopData) return; - - setStop(stopData); - const isIndian = slug.includes("indian"); - setBrandSlug(isIndian ? "indian-river-direct" : "tuxedo"); - setBrandAccent(isIndian ? "blue" : "green"); - - const { data: productsData } = await supabase - .from("products") - .select("*") - .eq("brand_id", stopData.brand_id) - .eq("active", true) as unknown as { data: Product[] | null }; - setProducts(productsData ?? []); - } - load(); - }, [slug]); - - if (!stop) { - return ( -
- -
- -
-

Stop Not Found

-
-
-
-
- ); - } - - const isBlue = brandAccent === "blue"; - const brandLabel = isBlue ? "Indian River Direct" : "Tuxedo Corn"; - - return ( -
- - -
- -
- - {/* Back navigation */} -
- - - - - All Stops - - / - {stop.city}, {stop.state} -
- - {/* Stop header */} -
-

- {brandLabel} -

-

- {stop.city},
{stop.state} -

-

- {isBlue - ? "Order fresh Florida citrus for pickup at this stop." - : "Order fresh Olathe Sweet™ sweet corn for pickup at this stop."} -

-
-
- - {/* Stop info */} -
-
-
-
- - - -
-
-

Date

-

{formatDate(stop.date)}

-
-
-
-
- - - -
-
-

Time

-

{stop.time}

-
-
-
-
- - - - -
-
-

Location

-

{stop.location}

-
-
-
-
- - {/* Available Products — editorial header */} -
-
-

Farm-Direct

-

- Available Products -

-
-

- Preorder for pickup — add items below and we will have them ready at the stop. -

-
- {products.length === 0 ? ( -
-

No products available for this stop.

-
- ) : ( -
- {products.map((product) => ( - - ))} -
- )} -
-
- -
- - -
- ); -} \ No newline at end of file