Fix API routes for Cloudflare Workers and enable preview URLs
- Remove unsupported next: { revalidate } option from API routes
- Add Cloudflare-specific cache configuration (cf.cacheTtl)
- Add User-Agent and Referer headers to bypass Plan API 403 errors
- Enable workers_dev and preview_urls in wrangler.jsonc to prevent disabling on deployment
This commit is contained in:
parent
d0bd636a43
commit
3c2368d886
File diff suppressed because it is too large
Load Diff
@ -18,8 +18,6 @@ interface PlanPlayersResponse {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
// Extract player name from HTML string
|
||||
function extractPlayerName(nameString: string): string {
|
||||
// Name format: '<a class="link" href="../player/...">PlayerName</a>'
|
||||
@ -32,9 +30,14 @@ export async function GET() {
|
||||
const playersResponse = await fetch(
|
||||
`${PLAN_BASE_URL}/v1/players?server=${SERVER_NAME}`,
|
||||
{
|
||||
next: { revalidate: 300 }, // Cache for 5 minutes
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; BiohazardVFX/1.0)',
|
||||
'Referer': PLAN_BASE_URL,
|
||||
},
|
||||
cf: {
|
||||
cacheTtl: 300,
|
||||
cacheEverything: true,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -25,9 +25,14 @@ export async function GET() {
|
||||
const overviewResponse = await fetch(
|
||||
`${PLAN_BASE_URL}/v1/serverOverview?server=${SERVER_NAME}`,
|
||||
{
|
||||
next: { revalidate: 30 }, // Cache for 30 seconds
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; BiohazardVFX/1.0)',
|
||||
'Referer': PLAN_BASE_URL,
|
||||
},
|
||||
cf: {
|
||||
cacheTtl: 30,
|
||||
cacheEverything: true,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import StickyFooter from '@/components/ui/footer';
|
||||
import { motion } from 'framer-motion';
|
||||
import { MessageCircle } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
@ -42,7 +40,7 @@ export function CustomFooter() {
|
||||
try {
|
||||
await navigator.clipboard.writeText('minecraft.biohazardvfx.com');
|
||||
toast.success('Server IP copied to clipboard!');
|
||||
} catch (error) {
|
||||
} catch {
|
||||
toast.error('Failed to copy IP address');
|
||||
}
|
||||
};
|
||||
@ -84,7 +82,7 @@ export function CustomFooter() {
|
||||
{section.title}
|
||||
</h3>
|
||||
{section.links.map((link, linkIndex) => {
|
||||
if (link.external) {
|
||||
if ('external' in link && link.external) {
|
||||
return (
|
||||
<motion.a
|
||||
key={linkIndex}
|
||||
@ -105,7 +103,7 @@ export function CustomFooter() {
|
||||
</span>
|
||||
</motion.a>
|
||||
);
|
||||
} else if (link.isButton) {
|
||||
} else if ('isButton' in link && link.isButton) {
|
||||
return (
|
||||
<motion.button
|
||||
key={linkIndex}
|
||||
@ -124,7 +122,7 @@ export function CustomFooter() {
|
||||
</span>
|
||||
</motion.button>
|
||||
);
|
||||
} else if (link.isStatic) {
|
||||
} else if ('isStatic' in link && link.isStatic) {
|
||||
return (
|
||||
<span
|
||||
key={linkIndex}
|
||||
|
||||
@ -76,19 +76,19 @@ export function Hero() {
|
||||
<span className="block text-primary break-words tracking-tighter text-shadow-md">
|
||||
<HoverRollingText
|
||||
text="Build."
|
||||
transition={{ duration: 0.6, delay: 0.05, ease: [0.4, 0, 0.2, 1] }}
|
||||
transition={{ duration: 0.6, delay: 0.05 }}
|
||||
/>
|
||||
</span>
|
||||
<span className="block text-secondary break-words tracking-normal text-shadow-sm">
|
||||
<HoverRollingText
|
||||
text="Explore."
|
||||
transition={{ duration: 0.6, delay: 0.05, ease: [0.4, 0, 0.2, 1] }}
|
||||
transition={{ duration: 0.6, delay: 0.05 }}
|
||||
/>
|
||||
</span>
|
||||
<span className="block text-accent break-words tracking-normal text-shadow-sm">
|
||||
<HoverRollingText
|
||||
text="Survive."
|
||||
transition={{ duration: 0.6, delay: 0.05, ease: [0.4, 0, 0.2, 1] }}
|
||||
transition={{ duration: 0.6, delay: 0.05 }}
|
||||
/>
|
||||
</span>
|
||||
</motion.h1>
|
||||
|
||||
@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
|
||||
import { motion } from 'motion/react';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Trophy, Clock, Calendar } from 'lucide-react';
|
||||
import { Trophy, Clock } from 'lucide-react';
|
||||
import { PlayerTooltip } from '@/components/player-tooltip';
|
||||
|
||||
interface LeaderboardPlayer {
|
||||
|
||||
@ -5,7 +5,6 @@ import { useTheme } from 'next-themes';
|
||||
|
||||
export function ThemeTransition() {
|
||||
const { theme, resolvedTheme } = useTheme();
|
||||
const [isTransitioning, setIsTransitioning] = useState(false);
|
||||
const [prevTheme, setPrevTheme] = useState<string | undefined>();
|
||||
const [capturedImage, setCapturedImage] = useState<string | null>(null);
|
||||
const overlayRef = useRef<HTMLDivElement>(null);
|
||||
@ -26,8 +25,6 @@ export function ThemeTransition() {
|
||||
useEffect(() => {
|
||||
const currentTheme = resolvedTheme || theme;
|
||||
if (prevTheme && prevTheme !== currentTheme && currentTheme && overlayRef.current && capturedImage) {
|
||||
setIsTransitioning(true);
|
||||
|
||||
// Set the captured image as background
|
||||
overlayRef.current.style.backgroundImage = `url(${capturedImage})`;
|
||||
overlayRef.current.style.backgroundSize = 'cover';
|
||||
@ -36,7 +33,6 @@ export function ThemeTransition() {
|
||||
overlayRef.current.classList.add('theme-wipe-active');
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setIsTransitioning(false);
|
||||
if (overlayRef.current) {
|
||||
overlayRef.current.classList.remove('theme-wipe-active');
|
||||
overlayRef.current.style.opacity = '0';
|
||||
|
||||
@ -9,7 +9,6 @@ const containerVariants = {
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.8,
|
||||
ease: "easeOut",
|
||||
staggerChildren: 0.1,
|
||||
},
|
||||
},
|
||||
@ -20,7 +19,7 @@ const itemVariants = {
|
||||
visible: {
|
||||
opacity: 1,
|
||||
x: 0,
|
||||
transition: { duration: 0.6, ease: "easeOut" },
|
||||
transition: { duration: 0.6 },
|
||||
},
|
||||
}
|
||||
|
||||
@ -29,7 +28,7 @@ const linkVariants = {
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.4, ease: "easeOut" },
|
||||
transition: { duration: 0.4 },
|
||||
},
|
||||
}
|
||||
|
||||
@ -39,7 +38,7 @@ const socialVariants = {
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
transition: {
|
||||
type: "spring",
|
||||
type: "spring" as const,
|
||||
stiffness: 200,
|
||||
damping: 10,
|
||||
},
|
||||
@ -53,7 +52,6 @@ const backgroundVariants = {
|
||||
scale: 1,
|
||||
transition: {
|
||||
duration: 2,
|
||||
ease: "easeOut",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
|
||||
const transition = {
|
||||
type: "spring",
|
||||
type: "spring" as const,
|
||||
mass: 0.5,
|
||||
damping: 11.5,
|
||||
stiffness: 100,
|
||||
@ -109,7 +109,7 @@ export const ProductItem = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const HoveredLink = ({ children, ...rest }: any) => {
|
||||
export const HoveredLink = ({ children, ...rest }: React.ComponentProps<typeof Link>) => {
|
||||
return (
|
||||
<Link
|
||||
{...rest}
|
||||
|
||||
@ -35,20 +35,21 @@ export const AnimatedTooltip = ({ items }: AnimatedTooltipProps) => {
|
||||
springConfig,
|
||||
);
|
||||
|
||||
const handleMouseMove = (event: any) => {
|
||||
const handleMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (animationFrameRef.current) {
|
||||
cancelAnimationFrame(animationFrameRef.current);
|
||||
}
|
||||
|
||||
animationFrameRef.current = requestAnimationFrame(() => {
|
||||
const halfWidth = event.target.offsetWidth / 2;
|
||||
const target = event.target as HTMLElement;
|
||||
const halfWidth = target.offsetWidth / 2;
|
||||
x.set(event.nativeEvent.offsetX - halfWidth);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{items.map((item, idx) => (
|
||||
{items.map((item) => (
|
||||
<div
|
||||
className="group relative -mr-4"
|
||||
key={item.name}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useState } from "react";
|
||||
|
||||
export const Component = () => {
|
||||
return (
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { MessageCircle } from "lucide-react";
|
||||
|
||||
export interface NavItem {
|
||||
label: string;
|
||||
href: string;
|
||||
@ -29,6 +27,5 @@ export const navigationItems: Array<NavItem | NavDropdown> = [
|
||||
label: "Community",
|
||||
href: "https://discord.gg/invite",
|
||||
external: true,
|
||||
icon: <MessageCircle className="h-4 w-4" />,
|
||||
},
|
||||
];
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
"zone_name": "biohazardvfx.com"
|
||||
}
|
||||
],
|
||||
"workers_dev": true,
|
||||
"preview_urls": true,
|
||||
"observability": {
|
||||
"enabled": true
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user