feat: make changelog, mod changelog, downloads, mods and vulnerability pages server-side rendered

This commit is contained in:
Dorian Niemiec 2024-09-07 20:56:08 +02:00
parent 7c47e05a3a
commit 81950a1fc4
17 changed files with 215 additions and 301 deletions

View file

@ -0,0 +1,66 @@
import { Metadata } from "next";
import clientPromise from "@/lib/db";
interface Page {
title: string;
content: string;
}
// baseURL [ENV]
export async function generateMetadata({
params
}: {
params: { slug: "string" };
}) {
let page: Page = {
title: "unknown mod",
content: "unknown mod"
};
let notFound = false;
try {
const client = await clientPromise;
const db = client.db();
const fetchedPage = (await db
.collection("pages")
.findOne({ slug: params.slug })) as unknown as Page;
if (fetchedPage) {
page = fetchedPage;
} else {
notFound = true;
}
} catch (err) {}
return {
title: `${page.title} change log - SVR.JS`,
description: `Keep track of the latest updates and improvements for ${page.title} with our comprehensive change log. Discover new features, bug fixes, and enhancements for each release of this SVR.JS mod.`,
openGraph: {
title: `${page.title} change log - SVR.JS`,
description: `Keep track of the latest updates and improvements for ${page.title} with our comprehensive change log. Discover new features, bug fixes, and enhancements for each release of this SVR.JS mod.`,
url: `https://svrjs.org/changelog/${params.slug}`,
type: "website",
images: [
{
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
width: 800,
height: 600,
alt: `${page.title} change log - SVR.JS`
}
]
},
twitter: {
card: "summary_large_image",
site: "@SVR_JS",
title: `${page.title} change log - SVR.JS`,
description: `Keep track of the latest updates and improvements for ${page.title} with our comprehensive change log. Discover new features, bug fixes, and enhancements for each release of this SVR.JS mod.`,
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
creator: "@SVR_JS"
}
};
}
const ContactLayout = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>;
};
export default ContactLayout;

View file

@ -1,74 +1,38 @@
"use client";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import React, { useEffect, useState } from "react"; import React from "react";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import Head from "next/head"; import Head from "next/head";
import clientPromise from "@/lib/db";
import { notFound } from "next/navigation";
const Page = ({ params }: { params: { slug: string } }) => { interface Page {
title: string;
content: string;
}
export const dynamic = "force-static";
const Page = async ({ params }: { params: { slug: string } }) => {
const { slug } = params; const { slug } = params;
const [page, setPage] = useState<{ title: string; content: string } | null>( let page: Page | null = null;
null let isNotFound = false;
);
const [loading, setLoading] = useState(true);
const [notFound, setNotFound] = useState(false);
useEffect(() => { try {
const fetchPage = async () => { const client = await clientPromise;
try { const db = client.db();
const response = await fetch(`/api/mdx/pages/${slug}`);
if (response.ok) {
const data = await response.json();
setPage(data);
return (document.title = `${data.title} Change Log - SVR.JS`);
} else {
if (response.status === 404) {
setNotFound(true);
return (document.title = "404 Not Found");
}
}
} catch (error) {
console.error("Failed to load page", error);
setNotFound(true);
} finally {
setLoading(false);
}
};
fetchPage(); const fetchedPage = (await db
}, [slug]); .collection("pages")
.findOne({ slug })) as unknown as Page;
if (fetchedPage) {
page = fetchedPage;
} else {
isNotFound = true;
}
} catch (err) {}
if (loading) { if (isNotFound) {
return ( notFound();
<>
<head>
<title>Mods Change Logs - SVR.JS</title>
</head>
<section className="wrapper container py-24 md:py-28 gap-4 flex flex-col">
<div className="mb-3">
<Skeleton className="w-[400px] h-[50px] rounded-md" />
</div>
<div className="flex flex-col gap-4">
<Skeleton className="w-[300px] h-[30px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
</div>
</section>
</>
);
}
if (notFound) {
return (
<section id="404error" className="flex-center flex-col wrapper container">
<h1 className="text-3xl md:text-5xl text-center">
<span className="text-red-500">404</span> Page not Found
</h1>
<p className="text-lg mt-3 text-muted-foreground">
Please return back to Home
</p>
</section>
);
} }
if (!page) { if (!page) {
@ -77,47 +41,6 @@ const Page = ({ params }: { params: { slug: string } }) => {
return ( return (
<> <>
<head>
<title>{page.title} Changelog - SVR.JS</title>
<meta
name="description"
content={`Keep track of the latest updates and improvements for ${page.title} with our comprehensive change log. Discover new features, bug fixes, and enhancements for each release of this SVR.JS mod.`}
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
property="og:title"
content={`${page.title} Changelog - SVR.JS`}
/>
<meta
property="og:description"
content={`Keep track of the latest updates and improvements for ${page.title} with our comprehensive change log. Discover new features, bug fixes, and enhancements for each release of this SVR.JS mod.`}
/>
<meta property="og:type" content="website" />
<meta
property="og:url"
content={`https://svrjs.org/changelog/${slug}`}
/>
<meta
property="og:image"
content="https://svrjs.vercel.app/metadata/svrjs-cover.png"
/>
<title>Documentation - SVR.JS</title>
<meta name="twitter:card" content="summary_large_image" />
<meta
name="twitter:title"
content={`${page.title} Changelog - SVR.JS`}
/>
<meta
name="twitter:description"
content={`Keep track of the latest updates and improvements for ${page.title} with our comprehensive change log. Discover new features, bug fixes, and enhancements for each release of this SVR.JS mod.`}
/>
<meta
name="twitter:image"
content="https://svrjs.vercel.app/metadata/svrjs-cover.png"
/>
</head>
<section className="wrapper container py-24 md:py-28 gap-2 flex flex-col"> <section className="wrapper container py-24 md:py-28 gap-2 flex flex-col">
<h1 className="text-3xl md:text-5xl pb-1 md:pb-2 font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400"> <h1 className="text-3xl md:text-5xl pb-1 md:pb-2 font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
{page.title} Change Log {page.title} Change Log
@ -130,4 +53,17 @@ const Page = ({ params }: { params: { slug: string } }) => {
); );
}; };
export async function generateStaticParams() {
try {
const client = await clientPromise;
const db = client.db();
const slugs = await db.collection("pages").find().toArray();
return slugs.map((element) => {
return { slug: element.slug };
});
} catch (err) {
return [];
}
}
export default Page; export default Page;

View file

@ -1,12 +1,10 @@
"use client";
import { useEffect, useState } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Download } from "lucide-react"; import { Download } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import { CHANGE_LOGS } from "@/constants/guidelines"; import { CHANGE_LOGS } from "@/constants/guidelines";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import clientPromise from "@/lib/db";
interface Bullet { interface Bullet {
point: string; point: string;
@ -19,61 +17,25 @@ interface LOGS {
bullets?: Bullet[]; // Make bullets optional bullets?: Bullet[]; // Make bullets optional
} }
const LogsPage: React.FC = () => { export const dynamic = "force-static";
const [downloads, setDownloads] = useState<LOGS[]>([]);
const [error, setError] = useState("");
const [loading, setLoading] = useState(true);
const fetchDownloads = async () => { const LogsPage: React.FC = async () => {
try { let error: Error | null = null;
const response = await fetch("/api/logs", { let downloads: LOGS[] = [];
method: "GET"
});
if (response.ok) {
const data: LOGS[] = await response.json();
setDownloads(data);
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error.message || "Failed to fetch downloads");
} finally {
setLoading(false);
}
};
useEffect(() => { try {
fetchDownloads(); const client = await clientPromise;
const db = client.db("downloadsDatabase");
const interval = setInterval(() => { downloads = (await db
fetchDownloads(); .collection("logs")
}, 10000); .find()
.toArray()) as unknown as LOGS[];
return () => clearInterval(interval); } catch (err) {
}, []); error = err as Error;
const reversedDownloads = [...downloads].reverse();
if (loading) {
return (
<>
<head>
<title>SVR.JS change log - SVR.JS</title>
</head>
<section className="wrapper container py-24 md:py-28 gap-4 flex flex-col">
<div className="mb-3">
<Skeleton className="w-[400px] h-[50px] rounded-md" />
</div>
<div className="flex flex-col gap-4">
<Skeleton className="w-[300px] h-[30px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
</div>
</section>
</>
);
} }
const reversedDownloads = [...downloads].reverse();
return ( return (
<section <section
id="logs" id="logs"
@ -85,7 +47,7 @@ const LogsPage: React.FC = () => {
<p className="md:text-lg text-muted-foreground text-start mb-6"> <p className="md:text-lg text-muted-foreground text-start mb-6">
See the changes done to SVR.JS web server. See the changes done to SVR.JS web server.
</p> </p>
{error && <p className="text-red-500">{error}</p>} {error && <p className="text-red-500">{error.message}</p>}
{reversedDownloads.map((download) => ( {reversedDownloads.map((download) => (
<div <div

View file

@ -1,6 +1,3 @@
"use client";
import { useEffect, useState } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Table, Table,
@ -13,7 +10,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import { Download } from "lucide-react"; import { Download } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { Skeleton } from "@/components/ui/skeleton"; import clientPromise from "@/lib/db";
interface Download { interface Download {
_id: string; _id: string;
@ -24,35 +21,22 @@ interface Download {
downloadLink?: string; // Optional downloadLink?: string; // Optional
} }
const DownloadPage: React.FC = () => { export const dynamic = "force-static";
const [downloads, setDownloads] = useState<Download[]>([]);
const [error, setError] = useState("");
const fetchDownloads = async () => { const DownloadPage: React.FC = async () => {
try { let error: Error | null = null;
const response = await fetch("/api/downloads", { let downloads: Download[] = [];
method: "GET"
});
if (response.ok) {
const data: Download[] = await response.json();
setDownloads(data);
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error.message);
}
};
useEffect(() => { try {
fetchDownloads(); const client = await clientPromise;
const db = client.db("downloadsDatabase");
const interval = setInterval(() => { downloads = (await db
fetchDownloads(); .collection("downloads")
}, 10000); .find()
.toArray()) as unknown as Download[];
return () => clearInterval(interval); } catch (err) {
}, []); error = err as Error;
}
return ( return (
<section <section
@ -73,7 +57,7 @@ const DownloadPage: React.FC = () => {
</Link> </Link>
. .
</p> </p>
{error && <p className="text-red-500">{error}</p>} {error && <p className="text-red-500">{error.message}</p>}
<Table> <Table>
<TableCaption>A list of all available downloads.</TableCaption> <TableCaption>A list of all available downloads.</TableCaption>
<TableHeader> <TableHeader>

View file

@ -1,6 +1,3 @@
"use client";
import { useEffect, useState } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
Table, Table,
@ -13,6 +10,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import { Download } from "lucide-react"; import { Download } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import clientPromise from "@/lib/db";
interface Mods { interface Mods {
_id: string; _id: string;
@ -23,35 +21,22 @@ interface Mods {
downloadLink: string; downloadLink: string;
} }
const ModsPage: React.FC = () => { export const dynamic = "force-static";
const [downloads, setDownloads] = useState<Mods[]>([]);
const [error, setError] = useState("");
const fetchDownloads = async () => { const ModsPage: React.FC = async () => {
try { let error: Error | null = null;
const response = await fetch("/api/mods", { let downloads: Mods[] = [];
method: "GET"
});
if (response.ok) {
const data: Mods[] = await response.json();
setDownloads(data);
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error);
}
};
useEffect(() => { try {
fetchDownloads(); const client = await clientPromise;
const db = client.db("downloadsDatabase");
const interval = setInterval(() => { downloads = (await db
fetchDownloads(); .collection("mods")
}, 10000); .find()
.toArray()) as unknown as Mods[];
return () => clearInterval(interval); } catch (err) {
}, []); error = err as Error;
}
return ( return (
<section <section
@ -78,7 +63,7 @@ const ModsPage: React.FC = () => {
</Link> </Link>
. .
</p> </p>
{error && <p className="text-red-500">{error}</p>} {error && <p className="text-red-500">{error.message}</p>}
<Table> <Table>
<TableCaption>A list of all available downloads.</TableCaption> <TableCaption>A list of all available downloads.</TableCaption>
<TableHeader> <TableHeader>

View file

@ -1,9 +1,8 @@
"use client";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import { VULNERABILITY } from "@/constants/guidelines"; import { VULNERABILITY } from "@/constants/guidelines";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import clientPromise from "@/lib/db";
interface Bullet { interface Bullet {
point: string; point: string;
@ -23,89 +22,39 @@ interface ModsVulnerability {
vulnerabilities: string; vulnerabilities: string;
} }
const Vulnerabilities = () => { const Vulnerabilities = async () => {
const [loading, setLoading] = useState(true); let downloads: Vulnerabilities[] = [];
const [downloads, setDownloads] = useState<Vulnerabilities[]>([]); let mods: ModsVulnerability[] = [];
const [mods, setMods] = useState<ModsVulnerability[]>([]); let error: Error | null = null;
const [error, setError] = useState("");
const fetchData = async () => { try {
try { const client = await clientPromise;
const response = await fetch("/api/vulnerabilities", { const db = client.db("downloadsDatabase");
method: "GET" downloads = (await db
}); .collection("vulnerabilities")
if (response.ok) { .find()
const data: Vulnerabilities[] = await response.json(); .toArray()) as unknown as Vulnerabilities[];
setDownloads(data); } catch (err) {
return (document.title = "Vulnerabilities - SVR.JS"); error = err as Error;
} else { }
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error.message || "Failed to fetch downloads");
} finally {
setLoading(false);
}
};
const fetchMods = async () => { try {
try { const client = await clientPromise;
const response = await fetch(`/api/mdx/pages`, { const db = client.db();
method: "GET"
});
if (response.ok) {
const data: ModsVulnerability[] = await response.json();
// Filter out entries where vulnerabilities is undefined or an empty string
const filteredMods = data.filter(
(mod) => mod.vulnerabilities && mod.vulnerabilities.trim() !== ""
);
setMods(filteredMods);
return (document.title = "Vulnerabilities - SVR.JS");
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (error: any) {
setError(error.message || "Failed to fetch vulnerabilities");
} finally {
setLoading(false);
}
};
useEffect(() => { const pages = (await db
fetchData(); .collection("pages")
fetchMods(); .find()
const interval = setInterval(() => { .toArray()) as unknown as ModsVulnerability[];
fetchData(); mods = pages.filter(
fetchMods(); (mod: ModsVulnerability) =>
}, 10000); mod.vulnerabilities && mod.vulnerabilities.trim() !== ""
);
return () => clearInterval(interval); } catch (err) {}
}, []);
const reversedDownloads = [...downloads].reverse(); const reversedDownloads = [...downloads].reverse();
const reversedMods = [...mods].reverse(); const reversedMods = [...mods].reverse();
if (loading) {
return (
<>
<head>
<title>Vulnerabilities - SVR.JS</title>
</head>
<section className="wrapper container py-24 md:py-28 gap-4 flex flex-col">
<div className="mb-3">
<Skeleton className="w-[400px] h-[50px] rounded-md" />
</div>
<div className="flex flex-col gap-4">
<Skeleton className="w-[300px] h-[30px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
<Skeleton className="w-[200px] h-[20px] rounded-md" />
</div>
</section>
</>
);
}
return ( return (
<section <section
id="vulnerabilities" id="vulnerabilities"
@ -121,7 +70,7 @@ const Vulnerabilities = () => {
vulnerability-reports@svrjs.org. We&apos;ll mitigate that vulnerability vulnerability-reports@svrjs.org. We&apos;ll mitigate that vulnerability
if it is possible. if it is possible.
</p> </p>
{error && <p className="text-red-500">{error}</p>} {error && <p className="text-red-500">{error.message}</p>}
{reversedDownloads.map((download) => ( {reversedDownloads.map((download) => (
<div <div
@ -161,4 +110,6 @@ const Vulnerabilities = () => {
); );
}; };
export const dynamic = "force-static";
export default Vulnerabilities; export default Vulnerabilities;

View file

@ -2,6 +2,7 @@
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { revalidatePath } from "next/cache";
export async function DELETE( export async function DELETE(
request: Request, request: Request,
@ -17,6 +18,7 @@ export async function DELETE(
const result = await collection.deleteOne({ _id: new ObjectId(id) }); const result = await collection.deleteOne({ _id: new ObjectId(id) });
if (result.deletedCount === 1) { if (result.deletedCount === 1) {
revalidatePath("/downloads");
return NextResponse.json({ message: "Log deleted successfully" }); return NextResponse.json({ message: "Log deleted successfully" });
} else { } else {
return NextResponse.json({ message: "Log not found" }, { status: 404 }); return NextResponse.json({ message: "Log not found" }, { status: 404 });

View file

@ -2,6 +2,7 @@
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { revalidatePath } from "next/cache";
export async function DELETE( export async function DELETE(
request: Request, request: Request,
@ -17,6 +18,7 @@ export async function DELETE(
const result = await collection.deleteOne({ _id: new ObjectId(id) }); const result = await collection.deleteOne({ _id: new ObjectId(id) });
if (result.deletedCount === 1) { if (result.deletedCount === 1) {
revalidatePath("/changelog");
return NextResponse.json({ message: "Log deleted successfully" }); return NextResponse.json({ message: "Log deleted successfully" });
} else { } else {
return NextResponse.json({ message: "Log not found" }, { status: 404 }); return NextResponse.json({ message: "Log not found" }, { status: 404 });

View file

@ -2,6 +2,7 @@
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { revalidatePath } from "next/cache";
export async function DELETE( export async function DELETE(
request: Request, request: Request,
@ -17,6 +18,7 @@ export async function DELETE(
const result = await collection.deleteOne({ _id: new ObjectId(id) }); const result = await collection.deleteOne({ _id: new ObjectId(id) });
if (result.deletedCount === 1) { if (result.deletedCount === 1) {
revalidatePath("/mods");
return NextResponse.json({ message: "Log deleted successfully" }); return NextResponse.json({ message: "Log deleted successfully" });
} else { } else {
return NextResponse.json({ message: "Log not found" }, { status: 404 }); return NextResponse.json({ message: "Log not found" }, { status: 404 });

View file

@ -1,6 +1,7 @@
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { revalidatePath } from "next/cache";
export async function DELETE( export async function DELETE(
request: Request, request: Request,
@ -19,6 +20,7 @@ export async function DELETE(
.collection("vulnerabilities") .collection("vulnerabilities")
.deleteOne({ _id: new ObjectId(id) }); .deleteOne({ _id: new ObjectId(id) });
if (result.deletedCount === 1) { if (result.deletedCount === 1) {
revalidatePath("/vulnerabilities");
return NextResponse.json( return NextResponse.json(
{ message: "Vulnerability deleted successfully" }, { message: "Vulnerability deleted successfully" },
{ status: 200 } { status: 200 }

View file

@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from "next/server"; import { NextRequest, NextResponse } from "next/server";
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { revalidatePath } from "next/cache";
export const GET = async ( export const GET = async (
req: NextRequest, req: NextRequest,
@ -59,6 +60,8 @@ export const PUT = async (
...result.value, ...result.value,
_id: result.value._id.toString() // Convert ObjectId to string _id: result.value._id.toString() // Convert ObjectId to string
}; };
revalidatePath(`/changelog/${slug}`);
revalidatePath("/vulnerabilities");
return NextResponse.json(serializedResult, { status: 200 }); return NextResponse.json(serializedResult, { status: 200 });
} else { } else {
return NextResponse.json({ message: "Page not found" }, { status: 404 }); return NextResponse.json({ message: "Page not found" }, { status: 404 });
@ -88,6 +91,8 @@ export const DELETE = async (
const result = await db.collection("pages").deleteOne({ slug }); const result = await db.collection("pages").deleteOne({ slug });
if (result.deletedCount > 0) { if (result.deletedCount > 0) {
revalidatePath(`/changelog/${slug}`);
revalidatePath("/vulnerabilities");
return NextResponse.json( return NextResponse.json(
{ message: "Page deleted successfully" }, { message: "Page deleted successfully" },
{ status: 200 } { status: 200 }

View file

@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from "next/server"; import { NextRequest, NextResponse } from "next/server";
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { revalidatePath } from "next/cache";
export const GET = async (req: NextRequest) => { export const GET = async (req: NextRequest) => {
const client = await clientPromise; const client = await clientPromise;
@ -32,6 +33,8 @@ export const POST = async (req: NextRequest) => {
try { try {
const newPage = { title, slug, content }; const newPage = { title, slug, content };
const result = await db.collection("pages").insertOne(newPage); const result = await db.collection("pages").insertOne(newPage);
revalidatePath(`/changelog/${slug}`);
revalidatePath("/vulnerabilities");
return NextResponse.json(newPage, { status: 201 }); return NextResponse.json(newPage, { status: 201 });
} catch (error) { } catch (error) {
console.error("Error creating page:", error); console.error("Error creating page:", error);

View file

@ -1,6 +1,7 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { ObjectId } from "mongodb"; import { ObjectId } from "mongodb";
import { revalidatePath } from "next/cache";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
@ -29,6 +30,7 @@ export async function PUT(
); );
if (result.modifiedCount > 0) { if (result.modifiedCount > 0) {
revalidatePath("/mods");
return NextResponse.json({ success: true }); return NextResponse.json({ success: true });
} else { } else {
return NextResponse.json({ return NextResponse.json({

View file

@ -1,5 +1,6 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { revalidatePath } from "next/cache";
// Force the API to use SSR instead of static generation // Force the API to use SSR instead of static generation
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
@ -19,5 +20,7 @@ export async function POST(request: Request) {
fileSize fileSize
}); });
revalidatePath("/downloads");
return NextResponse.json({ success: true, id: result.insertedId }); return NextResponse.json({ success: true, id: result.insertedId });
} }

View file

@ -1,5 +1,6 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { revalidatePath } from "next/cache";
// Force the API to use SSR instead of static generation // Force the API to use SSR instead of static generation
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
@ -17,5 +18,7 @@ export async function POST(request: Request) {
bullets bullets
}); });
revalidatePath("/changelog");
return NextResponse.json({ success: true, id: result.insertedId }); return NextResponse.json({ success: true, id: result.insertedId });
} }

View file

@ -1,5 +1,6 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { revalidatePath } from "next/cache";
// Force the API to use SSR instead of static generation // Force the API to use SSR instead of static generation
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
@ -19,5 +20,7 @@ export async function POST(request: Request) {
fileSize fileSize
}); });
revalidatePath("/mods");
return NextResponse.json({ success: true, id: result.insertedId }); return NextResponse.json({ success: true, id: result.insertedId });
} }

View file

@ -1,5 +1,6 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import clientPromise from "@/lib/db"; import clientPromise from "@/lib/db";
import { revalidatePath } from "next/cache";
// Force the API to use SSR instead of static generation // Force the API to use SSR instead of static generation
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
@ -16,5 +17,7 @@ export async function POST(request: Request) {
bullets bullets
}); });
revalidatePath("/vulnerabilities");
return NextResponse.json({ success: true, id: result.insertedId }); return NextResponse.json({ success: true, id: result.insertedId });
} }