(Feat) Init WebSite

This commit is contained in:
2026-06-22 23:03:02 +02:00
commit ea71039071
51 changed files with 11995 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
import fs from "node:fs";
import path from "node:path";
import matter from "gray-matter";
export type DevblogPost = {
slug: string;
title: string;
date: string;
excerpt: string;
author?: string;
tags?: string[];
game?: string;
content: string;
};
const POSTS_DIR = path.join(process.cwd(), "content", "devblog");
function ensureDir() {
if (!fs.existsSync(POSTS_DIR)) {
fs.mkdirSync(POSTS_DIR, { recursive: true });
}
}
export function getAllPosts(): DevblogPost[] {
ensureDir();
const files = fs
.readdirSync(POSTS_DIR)
.filter((f) => f.endsWith(".mdx") || f.endsWith(".md"));
const posts = files.map((file) => {
const slug = file.replace(/\.(mdx|md)$/, "");
const raw = fs.readFileSync(path.join(POSTS_DIR, file), "utf8");
const { data, content } = matter(raw);
return {
slug,
title: data.title ?? slug,
date: data.date ?? new Date().toISOString().slice(0, 10),
excerpt: data.excerpt ?? "",
author: data.author,
tags: data.tags ?? [],
game: data.game,
content,
} as DevblogPost;
});
return posts.sort((a, b) => (a.date < b.date ? 1 : -1));
}
export function getPost(slug: string): DevblogPost | undefined {
return getAllPosts().find((p) => p.slug === slug);
}
export function getPostsByGame(gameSlug: string): DevblogPost[] {
return getAllPosts().filter(
(p) => p.game === gameSlug || p.tags?.includes(gameSlug),
);
}
export function getAdjacentPosts(slug: string): {
newer?: DevblogPost;
older?: DevblogPost;
} {
const posts = getAllPosts();
const idx = posts.findIndex((p) => p.slug === slug);
if (idx === -1) return {};
return {
newer: idx > 0 ? posts[idx - 1] : undefined,
older: idx < posts.length - 1 ? posts[idx + 1] : undefined,
};
}
+27
View File
@@ -0,0 +1,27 @@
export type Game = {
slug: string;
title: string;
status: "in-development" | "released" | "coming-soon";
tagline: string;
description: string;
genres: string[];
releaseWindow?: string;
steamUrl?: string;
};
export const games: Game[] = [
{
slug: "project-one",
title: "Project One",
status: "in-development",
tagline: "A survival adventure across shifting horizons.",
description:
"Inspired by Raft and Aloft. Build, explore, and survive across drifting worlds. A new survival adventure currently in early development. The first world from Highland Games Studio.",
genres: ["Survival", "Crafting", "Exploration"],
releaseWindow: "TBA",
},
];
export function getGame(slug: string): Game | undefined {
return games.find((g) => g.slug === slug);
}