diff --git a/next.config.ts b/next.config.ts
index 582bf3e..d6a1ca2 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -9,7 +9,7 @@ const nextConfig: NextConfig = {
{
key: "Content-Security-Policy",
value:
- "frame-src 'self' https://player.twitch.tv https://embed.twitch.tv; frame-ancestors 'self';",
+ "frame-src 'self' https://tipilan.ee https://player.twitch.tv https://embed.twitch.tv; frame-ancestors 'self' https://tipilan.ee;",
},
{
key: "X-Frame-Options",
diff --git a/package.json b/package.json
index 7c55e31..5f2e22a 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,6 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"drizzle-orm": "^0.44.2",
- "gray-matter": "^4.0.3",
"lucide-react": "^0.522.0",
"material-symbols": "^0.31.8",
"next": "15.3.0",
@@ -36,7 +35,6 @@
"react-dom": "^19.1.1",
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
- "remark-gfm": "^4.0.1",
"tailwind-merge": "^3.3.1",
"three": "^0.178.0",
"tw-animate-css": "^1.3.4"
diff --git a/src/app/kodukord/page.tsx b/src/app/kodukord/page.tsx
index 68cb8a1..fe6428d 100644
--- a/src/app/kodukord/page.tsx
+++ b/src/app/kodukord/page.tsx
@@ -1,55 +1,56 @@
// app/kodukord/page.tsx (App Router)
-import fs from "node:fs";
-import path from "node:path";
-import ReactMarkdown from "react-markdown";
-import remarkGfm from "remark-gfm";
-import {vipnagorgialla} from "@/components/Vipnagorgialla";
+import ReactMarkdown, { Components } from "react-markdown";
+import { vipnagorgialla } from "@/components/Vipnagorgialla";
import SectionDivider from "@/components/SectionDivider";
-export const runtime = "nodejs"; // ensure fs is available (not Edge)
-export const dynamic = "force-static"; // read at build time
+export default async function Page() {
+ const file = Bun.file("src/data/kodukord.md");
+ const content = await file.text();
-export default function Page() {
- const filePath = path.join(process.cwd(), "src/data", "kodukord.md");
- const content = fs.readFileSync(filePath, "utf8");
+ return (
+
+
+ {/* Page title (separate from markdown headings) */}
+
+ Kodukord
+
- return (
-
-
- {/* Page title (separate from markdown headings) */}
-
- Kodukord
-
-
-
-
(
-
- ),
- h2: ({node, ...props}) => (
-
- ),
- ol: ({node, ...props}) => (
-
- ),
- ul: ({node, ...props}) => (
-
- ),
- p: ({node, ...props}) => (
-
- ),
- }}
- >
- {content}
-
-
-
-
-
+
+
(
+
+ {props.children}
+
+ ),
+ h2: (props) => (
+
+ {props.children}
+
+ ),
+ ol: (props) => (
+
+ {props.children}
+
+ ),
+ ul: (props) => (
+
+ ),
+ p: (props) => {props.children}
,
+ } as Components
+ }
+ >
+ {content}
+
- );
+
+
+
+
+ );
}
diff --git a/src/app/reeglid/[slug]/page.tsx b/src/app/reeglid/[slug]/page.tsx
index 5e4f735..d58f47e 100644
--- a/src/app/reeglid/[slug]/page.tsx
+++ b/src/app/reeglid/[slug]/page.tsx
@@ -1,49 +1,103 @@
-import {vipnagorgialla} from "@/components/Vipnagorgialla";
-import path from "node:path";
-import fs from "node:fs/promises";
-import ReactMarkdown from "react-markdown";
+import { notFound } from "next/navigation";
+import ReactMarkdown, { Components } from "react-markdown";
+import { vipnagorgialla } from "@/components/Vipnagorgialla";
import SectionDivider from "@/components/SectionDivider";
-type Props = {
- params: Promise<{ slug: string }>;
-};
-
-export default async function RulePage({params}: Props) {
- const {slug} = await params;
-
- const filePath = path.join(process.cwd(), "src/data/rules", `${slug}.md`);
- let file: string;
-
- try {
- file = await fs.readFile(filePath, "utf8");
- } catch {
- file = `# ${slug.toUpperCase()} REEGLID\n\nSisu hetkel puudub.`;
- }
-
- const data = {title: undefined as string | undefined};
-
- return (
- <>
-
-
- {data.title || `${slug.toUpperCase()} REEGLID`}
-
-
-
- {file}
-
-
-
-
- >
- );
+// Map of valid slugs to their corresponding file paths and titles
+const rulesMap = {
+ lol: {
+ filePath: "src/data/rules/lol.md",
+ title: "LOL Reeglid",
+ },
+ cs2: {
+ filePath: "src/data/rules/cs2.md",
+ title: "CS2 Reeglid",
+ },
+} as const;
+
+type RuleSlug = keyof typeof rulesMap;
+
+interface PageProps {
+ params: Promise<{ slug: string }>;
+}
+
+async function getRuleContent(slug: string) {
+ if (!Object.keys(rulesMap).includes(slug)) {
+ return null;
+ }
+
+ const ruleConfig = rulesMap[slug as RuleSlug];
+
+ try {
+ const file = Bun.file(ruleConfig.filePath);
+ const content = await file.text();
+ return {
+ content,
+ title: ruleConfig.title,
+ };
+ } catch (error) {
+ console.error(`Error reading rule file for slug ${slug}:`, error);
+ return null;
+ }
+}
+
+export default async function RulePage({ params }: PageProps) {
+ const { slug } = await params;
+ const ruleData = await getRuleContent(slug);
+
+ if (!ruleData) {
+ notFound();
+ }
+
+ const headingStyle = `text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold uppercase italic text-[#2A2C3F] dark:text-[#EEE5E5]`;
+
+ return (
+
+
+
+ {ruleData.title}
+
+
+
+
(
+
+ {props.children}
+
+ ),
+ h2: (props) => (
+
+ {props.children}
+
+ ),
+ ol: (props) => (
+
+ {props.children}
+
+ ),
+ ul: (props) => (
+
+ ),
+ p: (props) => {props.children}
,
+ } as Components
+ }
+ >
+ {ruleData.content}
+
+
+
+
+
+
+ );
+}
+
+export async function generateStaticParams() {
+ return Object.keys(rulesMap).map((slug) => ({
+ slug,
+ }));
}
diff --git a/src/app/reeglid/page.tsx b/src/app/reeglid/page.tsx
index 4afaf1e..167893e 100644
--- a/src/app/reeglid/page.tsx
+++ b/src/app/reeglid/page.tsx
@@ -1,64 +1,52 @@
-import {vipnagorgialla} from "@/components/Vipnagorgialla";
+import { vipnagorgialla } from "@/components/Vipnagorgialla";
import Link from "next/link";
import SectionDivider from "@/components/SectionDivider";
export default function RulesMenu() {
- const headingStyle = `text-5xl sm:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] dark:text-[#EEE5E5]`;
-
- const boxStyle = `-skew-x-2 md:-skew-x-5 text-white md:px-12 hover:scale-103 transition-all duration-150 w-full md:w-xl lg:w-[400px]`;
-
- const boxTextStyle = `text-3xl ${vipnagorgialla.className} font-bold uppercase text-[#EEE5E5] pb-2`;
+ const headingStyle = `text-4xl md:text-5xl lg:text-6xl ${vipnagorgialla.className} font-bold italic text-[#2A2C3F] dark:text-[#EEE5E5] uppercase`;
- // const SectionDivider = () =>
;
+ const boxStyle = `-skew-x-2 md:-skew-x-5 text-white md:px-12 hover:scale-103 transition-all duration-150 w-full md:w-xl lg:w-[400px]`;
- return (
-
-
-
- REEGLID
-
+ const boxTextStyle = `text-3xl ${vipnagorgialla.className} font-bold uppercase text-[#EEE5E5] pb-2`;
-
-
-
-
- Kodukord
-
-
-
+ // const SectionDivider = () =>
;
-
-
-
- CS2 reeglid
-
-
-
+ return (
+
+
+
+ REEGLID
+
+
+
+
+
Kodukord
+
+
-
-
-
- LoL reeglid
-
-
-
+
+
+
CS2 reeglid
+
+
- {/* Minitourn. link coming soon*/}
- {/*
*/}
-
-
- Miniturniiride reeglid
-
-
- {/**/}
-
-
+
+
+
LoL reeglid
-
-
-
+
+
+ {/* Minitourn. link coming soon*/}
+ {/*
*/}
+
+
Miniturniiride reeglid
+
+ {/**/}
- );
-}
\ No newline at end of file
+
+
+
+
+ );
+}
diff --git a/src/app/striim/page.tsx b/src/app/striim/page.tsx
index a3384b7..1d1d7bf 100644
--- a/src/app/striim/page.tsx
+++ b/src/app/striim/page.tsx
@@ -50,7 +50,7 @@ export default function Home() {
{/* Stream iframe from Twitch */}