mirror of
https://github.com/mleem97/gregWiki.git
synced 2026-04-11 03:29:19 +02:00
Merge Docusaurus site: all content under docs/, align with gregFramework split layout
- Move markdown and wiki-import tree into docs/; keep app shell at repo root - Point docusaurus docs path to docs/; edit links to mleem97/gregWiki - Sync and i18n scripts use gregWiki root and ../.wiki under gregFramework - Sidebars: workspace layout from root docs ids; plugins under mods/extensions - Fix redirects, module catalog URLs, release note paths, and wiki-import category keys - Update repo inventory for split repos; Dockerfile for single-repo context Made-with: Cursor
This commit is contained in:
159
src/components/ModReleasePage.tsx
Normal file
159
src/components/ModReleasePage.tsx
Normal file
@@ -0,0 +1,159 @@
|
||||
import React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
import Translate from '@docusaurus/Translate';
|
||||
|
||||
type ReleaseKind = 'mod' | 'plugin';
|
||||
|
||||
type ModReleasePageProps = {
|
||||
title: string;
|
||||
kind: ReleaseKind;
|
||||
dllName: string;
|
||||
description: string;
|
||||
version?: string;
|
||||
author?: string;
|
||||
category?: string;
|
||||
dependencies?: string[];
|
||||
codeLanguages?: string[];
|
||||
releaseReady?: boolean;
|
||||
banner?: string;
|
||||
releaseNotesPath?: string;
|
||||
/** If set, replaces the default installation steps (e.g. MelonLoader `Plugins/` vs `Mods/`). */
|
||||
installation?: React.ReactNode;
|
||||
};
|
||||
|
||||
function toTitleCase(value: ReleaseKind): string {
|
||||
return value.charAt(0).toUpperCase() + value.slice(1);
|
||||
}
|
||||
|
||||
export default function ModReleasePage({
|
||||
title,
|
||||
kind,
|
||||
dllName,
|
||||
description,
|
||||
version = 'NotReleasedYet',
|
||||
author = 'FrikaMF Community',
|
||||
category = 'Mod',
|
||||
dependencies = [],
|
||||
codeLanguages = ['C#'],
|
||||
releaseReady = false,
|
||||
banner,
|
||||
releaseNotesPath,
|
||||
installation,
|
||||
}: ModReleasePageProps): JSX.Element {
|
||||
const downloadPath = `/${kind}/${dllName}`;
|
||||
const downloadUrl =
|
||||
typeof window !== 'undefined' ? new URL(downloadPath, window.location.origin).toString() : downloadPath;
|
||||
const normalizedReleaseNotesPath = releaseNotesPath?.startsWith('/mods/')
|
||||
? `/wiki${releaseNotesPath}`
|
||||
: releaseNotesPath;
|
||||
|
||||
return (
|
||||
<div className="mod-release-page">
|
||||
<section className="mod-release-hero">
|
||||
<p className="mod-release-badge">{toTitleCase(kind)}</p>
|
||||
<h1>{title}</h1>
|
||||
<p>
|
||||
{banner ?? (
|
||||
<Translate id="modRelease.heroDefaultBanner">Official release download and module details</Translate>
|
||||
)}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mod-release-layout">
|
||||
<article className="mod-release-content">
|
||||
<h2>
|
||||
<Translate id="modRelease.descriptionTitle">Description</Translate>
|
||||
</h2>
|
||||
<p>{description}</p>
|
||||
|
||||
<h2>
|
||||
<Translate id="modRelease.installationTitle">Installation</Translate>
|
||||
</h2>
|
||||
{installation ?? (
|
||||
<ol>
|
||||
<li>
|
||||
<Translate id="modRelease.installStepOne">Download the release DLL.</Translate>
|
||||
</li>
|
||||
<li>
|
||||
<Translate id="modRelease.installStepTwo">Copy it to your Data Center `Mods/` folder.</Translate>
|
||||
</li>
|
||||
<li>
|
||||
<Translate id="modRelease.installStepThree">Start the game with MelonLoader.</Translate>
|
||||
</li>
|
||||
</ol>
|
||||
)}
|
||||
|
||||
<h2>
|
||||
<Translate id="modRelease.dllRouteTitle">Direct DLL Route</Translate>
|
||||
</h2>
|
||||
<p>
|
||||
<code>{downloadPath}</code>
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<aside className="mod-release-sidebar" aria-label="Download Sidebar">
|
||||
<div className="mod-release-sidebar-card">
|
||||
<h3>
|
||||
<Translate id="modRelease.sidebarTitle">Download</Translate>
|
||||
</h3>
|
||||
|
||||
{releaseReady ? (
|
||||
<a className="button button--primary button--lg mod-release-download-btn" href={downloadUrl}>
|
||||
<Translate id="modRelease.downloadButton">Download DLL</Translate>
|
||||
</a>
|
||||
) : (
|
||||
<button className="button button--primary button--lg mod-release-download-btn" disabled type="button">
|
||||
<Translate id="modRelease.notReleasedYet">NotReleasedYet</Translate>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{normalizedReleaseNotesPath ? (
|
||||
<Link className="button button--secondary button--sm mod-release-secondary-btn" to={normalizedReleaseNotesPath}>
|
||||
<Translate id="modRelease.releaseNotesButton">Open module docs</Translate>
|
||||
</Link>
|
||||
) : null}
|
||||
|
||||
<dl className="mod-release-meta-list">
|
||||
<div>
|
||||
<dt>
|
||||
<Translate id="modRelease.metaVersion">Version</Translate>
|
||||
</dt>
|
||||
<dd>{version}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>
|
||||
<Translate id="modRelease.metaAuthor">Author</Translate>
|
||||
</dt>
|
||||
<dd>{author}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>
|
||||
<Translate id="modRelease.metaCategory">Category</Translate>
|
||||
</dt>
|
||||
<dd>{category}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>
|
||||
<Translate id="modRelease.metaDependencies">Dependencies</Translate>
|
||||
</dt>
|
||||
<dd>{dependencies.join(', ')}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>
|
||||
<Translate id="modRelease.metaCodeLanguage">Code Language</Translate>
|
||||
</dt>
|
||||
<dd>{codeLanguages.join(', ')}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<p className="mod-release-sidebar-note">
|
||||
<Translate id="modRelease.sidebarHint">
|
||||
The download route redirects to the latest GitHub release asset.
|
||||
</Translate>
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
650
src/css/custom.css
Normal file
650
src/css/custom.css
Normal file
@@ -0,0 +1,650 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Space+Grotesk:wght@300;500;700&display=swap");
|
||||
@import "tailwindcss";
|
||||
|
||||
/* Luminescent Architect — design tokens (see docs/contributors/luminescent-design-system.md) */
|
||||
@theme {
|
||||
--color-background: #001110;
|
||||
--color-surface: #001110;
|
||||
--color-surface-dim: #001110;
|
||||
--color-surface-bright: #00322f;
|
||||
--color-surface-variant: #002b29;
|
||||
--color-surface-container-lowest: #000000;
|
||||
--color-surface-container-low: #001715;
|
||||
--color-surface-container: #001e1c;
|
||||
--color-surface-container-high: #002422;
|
||||
--color-surface-container-highest: #002b29;
|
||||
--color-on-background: #c0fcf6;
|
||||
--color-on-surface: #c0fcf6;
|
||||
--color-on-surface-variant: #7cb6b0;
|
||||
--color-primary: #61f4d8;
|
||||
--color-primary-dim: #4fe5ca;
|
||||
--color-primary-container: #08c1a6;
|
||||
--color-primary-fixed: #61f4d8;
|
||||
--color-primary-fixed-dim: #4fe5ca;
|
||||
--color-on-primary: #00594c;
|
||||
--color-on-primary-container: #00332b;
|
||||
--color-on-primary-fixed: #00443a;
|
||||
--color-on-primary-fixed-variant: #006455;
|
||||
--color-secondary: #1cede1;
|
||||
--color-secondary-dim: #00ded3;
|
||||
--color-secondary-container: #006a65;
|
||||
--color-secondary-fixed: #1cede1;
|
||||
--color-secondary-fixed-dim: #00ded3;
|
||||
--color-on-secondary: #00534e;
|
||||
--color-on-secondary-container: #dbfffa;
|
||||
--color-on-secondary-fixed-variant: #005d58;
|
||||
--color-tertiary: #64d0ff;
|
||||
--color-tertiary-dim: #00b6eb;
|
||||
--color-tertiary-container: #0ac4fd;
|
||||
--color-tertiary-fixed: #0ac4fd;
|
||||
--color-on-tertiary: #00445a;
|
||||
--color-on-tertiary-container: #00394d;
|
||||
--color-outline: #457f7a;
|
||||
--color-outline-variant: #0f514c;
|
||||
--color-error: #ff716c;
|
||||
--color-error-dim: #d7383b;
|
||||
--color-error-container: #9f0519;
|
||||
--color-on-error: #490006;
|
||||
--color-on-error-container: #ffa8a3;
|
||||
--color-inverse-surface: #e4fffb;
|
||||
--color-inverse-on-surface: #225e5a;
|
||||
--color-inverse-primary: #006c5c;
|
||||
--color-surface-tint: #61f4d8;
|
||||
/* Legacy aliases (pages / older class names) */
|
||||
--color-app-bg: #001110;
|
||||
--color-text-main: #c0fcf6;
|
||||
--color-text-soft: #7cb6b0;
|
||||
--color-text-muted: #5a9a94;
|
||||
--color-accent-green: #61f4d8;
|
||||
--color-accent-green-deep: #08c1a6;
|
||||
--color-accent-pink: #64d0ff;
|
||||
--color-accent-violet: #1cede1;
|
||||
--color-code-bg: #001110;
|
||||
--color-code-surface: #002b29;
|
||||
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-headline: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: "JetBrains Mono", ui-monospace, "Cascadia Code", monospace;
|
||||
}
|
||||
|
||||
:root,
|
||||
[data-theme="dark"] {
|
||||
--ifm-color-primary: #61f4d8;
|
||||
--ifm-color-primary-dark: #4fe5ca;
|
||||
--ifm-color-primary-darker: #08c1a6;
|
||||
--ifm-color-primary-light: #7ff7e4;
|
||||
--ifm-color-primary-lighter: #bafdf1;
|
||||
--ifm-background-color: var(--color-background);
|
||||
--ifm-color-content: var(--color-on-surface);
|
||||
--ifm-color-content-secondary: var(--color-on-surface-variant);
|
||||
--ifm-font-family-base: var(--font-sans);
|
||||
--ifm-heading-font-family: var(--font-headline);
|
||||
--ifm-font-family-monospace: var(--font-mono);
|
||||
--ifm-navbar-height: 72px;
|
||||
--ifm-navbar-background-color: rgba(0, 17, 16, 0.8);
|
||||
--ifm-card-background-color: var(--color-surface-container);
|
||||
--ifm-code-font-size: 0.9rem;
|
||||
--ifm-pre-background: var(--color-surface-container-highest);
|
||||
--ifm-global-shadow-lw: 0 0 32px -4px rgba(0, 191, 165, 0.1);
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
html.dark,
|
||||
html[data-theme="dark"] {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-on-surface);
|
||||
background-color: var(--color-background);
|
||||
background-image:
|
||||
radial-gradient(circle at 50% 50%, rgba(0, 191, 165, 0.05) 0%, transparent 70%),
|
||||
radial-gradient(circle at 12% 0%, rgba(97, 244, 216, 0.06), transparent 50%),
|
||||
linear-gradient(180deg, var(--color-background) 0%, var(--color-surface-container-low) 100%);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-on-primary);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--color-surface-container);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(180deg, rgba(97, 244, 216, 0.45), rgba(28, 237, 225, 0.35));
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: linear-gradient(180deg, rgba(97, 244, 216, 0.65), rgba(100, 208, 255, 0.45));
|
||||
}
|
||||
|
||||
/* Glass top bar — no hard bottom border; depth via blur + tinted shadow */
|
||||
.navbar {
|
||||
border: 0;
|
||||
-webkit-backdrop-filter: blur(20px) saturate(140%);
|
||||
backdrop-filter: blur(20px) saturate(140%);
|
||||
background: rgba(0, 17, 16, 0.8) !important;
|
||||
box-shadow: 0 0 32px -4px rgba(0, 191, 165, 0.1);
|
||||
}
|
||||
|
||||
.navbar__title {
|
||||
font-family: var(--font-headline);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--color-on-surface);
|
||||
}
|
||||
|
||||
.navbar__item .navbar__link {
|
||||
font-family: var(--font-headline);
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.06em;
|
||||
font-size: 0.875rem;
|
||||
text-transform: none;
|
||||
color: rgba(192, 252, 246, 0.7);
|
||||
transition: color 0.25s ease;
|
||||
}
|
||||
|
||||
.navbar__item .navbar__link:hover {
|
||||
color: var(--color-on-surface);
|
||||
}
|
||||
|
||||
.navbar__item .navbar__link--active {
|
||||
color: var(--color-primary);
|
||||
box-shadow: inset 0 -2px 0 0 var(--color-primary);
|
||||
}
|
||||
|
||||
.navbar [class*="colorModeToggle"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.nav-right-icon {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
border-radius: 999px;
|
||||
backdrop-filter: blur(12px);
|
||||
background: rgba(0, 30, 28, 0.65);
|
||||
box-shadow: inset 0 0 0 1px rgba(15, 81, 76, 0.15);
|
||||
}
|
||||
|
||||
.nav-icon-only {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.nav-icon-only::before {
|
||||
font-size: 0.95rem;
|
||||
color: var(--color-on-surface-variant);
|
||||
}
|
||||
|
||||
.nav-link-mods::before {
|
||||
content: "🧩";
|
||||
}
|
||||
|
||||
.nav-link-discord::before {
|
||||
content: "💬";
|
||||
}
|
||||
|
||||
.nav-link-support::before {
|
||||
content: "🛟";
|
||||
}
|
||||
|
||||
.nav-link-github::before {
|
||||
content: "⌁";
|
||||
}
|
||||
|
||||
.nav-locale::before {
|
||||
content: "🌐";
|
||||
}
|
||||
|
||||
/* Editorial bleed + hero (homepage) */
|
||||
.editorial-bleed {
|
||||
background: radial-gradient(circle at 50% 50%, rgba(0, 191, 165, 0.05) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
.hero-glow {
|
||||
box-shadow: 0 0 80px -20px rgba(97, 244, 216, 0.15);
|
||||
}
|
||||
|
||||
.hero-motion-wrap {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
.bg-hero-gradient {
|
||||
background:
|
||||
radial-gradient(circle at 50% -8%, rgba(97, 244, 216, 0.12), transparent 52%),
|
||||
radial-gradient(circle at 14% 68%, rgba(28, 237, 225, 0.08), transparent 48%),
|
||||
radial-gradient(circle at 84% 62%, rgba(100, 208, 255, 0.08), transparent 48%);
|
||||
}
|
||||
|
||||
.hero-particles,
|
||||
.hero-orb {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hero-particles {
|
||||
inset: 0;
|
||||
opacity: 0.22;
|
||||
background-image:
|
||||
radial-gradient(circle at 18% 26%, rgba(192, 252, 246, 0.08) 0 1px, transparent 1px),
|
||||
radial-gradient(circle at 72% 38%, rgba(97, 244, 216, 0.06) 0 1px, transparent 1px);
|
||||
background-size: 280px 220px;
|
||||
}
|
||||
|
||||
.hero-orb {
|
||||
width: clamp(12rem, 20vw, 18rem);
|
||||
height: clamp(12rem, 20vw, 18rem);
|
||||
border-radius: 999px;
|
||||
filter: blur(120px);
|
||||
mix-blend-mode: screen;
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
.hero-orb-pink {
|
||||
top: 6%;
|
||||
right: 8%;
|
||||
background: rgba(100, 208, 255, 0.45);
|
||||
}
|
||||
|
||||
.hero-orb-green {
|
||||
bottom: 12%;
|
||||
left: 6%;
|
||||
background: rgba(97, 244, 216, 0.35);
|
||||
}
|
||||
|
||||
.homepage-logo-title {
|
||||
font-family: var(--font-headline);
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.text-gradient-brand {
|
||||
background-image: linear-gradient(90deg, var(--color-primary), var(--color-secondary), var(--color-tertiary));
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.text-reveal-glow {
|
||||
text-shadow: 0 0 28px rgba(97, 244, 216, 0.18);
|
||||
}
|
||||
|
||||
/* Tonal sectioning — avoid 1px rules; optional subtle top fade only */
|
||||
.section-border {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.section-surface-alt {
|
||||
background-color: var(--color-surface-container-low);
|
||||
}
|
||||
|
||||
/* Glass cards */
|
||||
.glass-card {
|
||||
background: rgba(0, 30, 28, 0.8);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.app-card {
|
||||
background: linear-gradient(180deg, rgba(0, 30, 28, 0.85) 0%, rgba(0, 23, 21, 0.9) 100%);
|
||||
border: 1px solid rgba(15, 81, 76, 0.1);
|
||||
box-shadow: 0 18px 36px rgba(0, 0, 0, 0.35);
|
||||
-webkit-backdrop-filter: blur(12px) saturate(125%);
|
||||
backdrop-filter: blur(12px) saturate(125%);
|
||||
transition: transform 0.28s ease, box-shadow 0.28s ease, border-color 0.28s ease;
|
||||
}
|
||||
|
||||
.app-card-glow {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.app-card-glow::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -1px;
|
||||
border-radius: inherit;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 0 24px rgba(97, 244, 216, 0.08);
|
||||
}
|
||||
|
||||
.app-card-motion:hover {
|
||||
transform: translateY(-5px);
|
||||
border-color: rgba(97, 244, 216, 0.25);
|
||||
box-shadow: 0 24px 42px rgba(0, 0, 0, 0.4), 0 0 32px -4px rgba(0, 191, 165, 0.12);
|
||||
}
|
||||
|
||||
.btn-primary,
|
||||
.btn-outline,
|
||||
.btn-social {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
text-decoration: none !important;
|
||||
transition: transform 0.25s ease, box-shadow 0.25s ease, background 0.25s ease, color 0.25s ease;
|
||||
}
|
||||
|
||||
/* Primary CTA: 135° primary → primary-container, on-primary text */
|
||||
.btn-primary {
|
||||
border: 1px solid transparent;
|
||||
color: var(--color-on-primary);
|
||||
font-family: var(--font-headline);
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-container) 100%);
|
||||
box-shadow: 0 0 32px -4px rgba(0, 191, 165, 0.2);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
color: var(--color-on-primary);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 0 20px rgba(97, 244, 216, 0.3), 0 14px 28px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
/* Secondary: ghost border outline-variant @ 40% */
|
||||
.btn-outline {
|
||||
border: 1px solid rgba(15, 81, 76, 0.4);
|
||||
color: var(--color-on-surface);
|
||||
font-family: var(--font-headline);
|
||||
font-weight: 700;
|
||||
background: rgba(0, 17, 16, 0.5);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
color: var(--color-on-surface);
|
||||
border-color: var(--color-primary);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.btn-social {
|
||||
border: 1px solid transparent;
|
||||
color: var(--color-on-surface-variant);
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
border-radius: 0.75rem;
|
||||
padding: 0.6rem 0.95rem;
|
||||
background: rgba(0, 30, 28, 0.72);
|
||||
box-shadow: inset 0 0 0 1px rgba(15, 81, 76, 0.15);
|
||||
}
|
||||
|
||||
.btn-social:hover {
|
||||
color: var(--color-on-surface);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: inset 0 0 0 1px rgba(97, 244, 216, 0.25);
|
||||
}
|
||||
|
||||
.btn-primary:focus-visible,
|
||||
.btn-outline:focus-visible,
|
||||
.btn-social:focus-visible {
|
||||
outline: 2px solid rgba(97, 244, 216, 0.65);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.btn-primary:focus,
|
||||
.btn-outline:focus,
|
||||
.btn-social:focus {
|
||||
outline: 2px solid rgba(97, 244, 216, 0.65);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.theme-doc-root .theme-doc-sidebar-container {
|
||||
border: 0;
|
||||
background: var(--color-surface-container-low);
|
||||
box-shadow: inset -1px 0 0 rgba(15, 81, 76, 0.12);
|
||||
}
|
||||
|
||||
.menu {
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.menu__link {
|
||||
margin: 0.2rem 0;
|
||||
border-radius: 0.5rem;
|
||||
border-left: 4px solid transparent;
|
||||
padding-left: 0.75rem;
|
||||
color: var(--color-on-surface-variant);
|
||||
font-weight: 500;
|
||||
transition: color 0.22s ease, background 0.22s ease, border-color 0.22s ease;
|
||||
}
|
||||
|
||||
.menu__link:hover {
|
||||
color: var(--color-on-surface);
|
||||
background: rgba(97, 244, 216, 0.06);
|
||||
}
|
||||
|
||||
.menu__link--active {
|
||||
color: var(--color-on-surface) !important;
|
||||
background: rgba(97, 244, 216, 0.1) !important;
|
||||
border-left-color: var(--color-primary) !important;
|
||||
}
|
||||
|
||||
.theme-doc-markdown {
|
||||
line-height: 1.74;
|
||||
}
|
||||
|
||||
.theme-doc-markdown h1,
|
||||
.theme-doc-markdown h2,
|
||||
.theme-doc-markdown h3,
|
||||
.theme-doc-markdown h4 {
|
||||
font-family: var(--font-headline);
|
||||
letter-spacing: -0.015em;
|
||||
color: var(--color-on-surface);
|
||||
}
|
||||
|
||||
.theme-doc-markdown h2,
|
||||
.theme-doc-markdown h3 {
|
||||
border: 0;
|
||||
margin-top: 2.2rem;
|
||||
}
|
||||
|
||||
.theme-doc-markdown h2::after,
|
||||
.theme-doc-markdown h3::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 64px;
|
||||
height: 2px;
|
||||
margin-top: 0.6rem;
|
||||
background: linear-gradient(90deg, rgba(97, 244, 216, 0.55), rgba(28, 237, 225, 0.45));
|
||||
border-radius: 999px;
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.theme-doc-markdown p,
|
||||
.theme-doc-markdown li {
|
||||
color: var(--color-on-surface-variant);
|
||||
}
|
||||
|
||||
.theme-doc-markdown a {
|
||||
color: var(--color-primary);
|
||||
text-decoration-color: rgba(97, 244, 216, 0.35);
|
||||
}
|
||||
|
||||
.theme-doc-markdown a:hover {
|
||||
color: var(--color-secondary);
|
||||
text-decoration-color: rgba(28, 237, 225, 0.55);
|
||||
}
|
||||
|
||||
.theme-doc-markdown :not(pre) > code {
|
||||
color: var(--color-on-surface);
|
||||
background: var(--color-surface-container-high);
|
||||
box-shadow: inset 0 0 0 1px rgba(15, 81, 76, 0.15);
|
||||
border-radius: 0.42rem;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.84em;
|
||||
padding: 0.12rem 0.34rem;
|
||||
}
|
||||
|
||||
.theme-doc-markdown pre {
|
||||
background: linear-gradient(180deg, var(--color-surface-container-highest) 0%, var(--color-surface-container-high) 100%) !important;
|
||||
border-radius: 0.75rem;
|
||||
border: 0;
|
||||
box-shadow: 0 18px 32px rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(15, 81, 76, 0.12);
|
||||
}
|
||||
|
||||
.theme-doc-markdown pre code {
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.footer {
|
||||
border: 0;
|
||||
border-top: 1px solid rgba(0, 36, 34, 0.15);
|
||||
background: var(--color-background);
|
||||
color: rgba(192, 252, 246, 0.4);
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.footer__title {
|
||||
font-family: var(--font-headline);
|
||||
color: #00bfa5;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: rgba(192, 252, 246, 0.4);
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.footer-link-icon {
|
||||
position: relative;
|
||||
padding-left: 1.4rem;
|
||||
}
|
||||
|
||||
.footer-link-icon::before {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.footer-link-github::before {
|
||||
content: "⌁";
|
||||
}
|
||||
|
||||
.footer-link-discord::before {
|
||||
content: "💬";
|
||||
}
|
||||
|
||||
.footer-link-support::before {
|
||||
content: "🛟";
|
||||
}
|
||||
|
||||
.button.button--primary {
|
||||
border: 0;
|
||||
color: var(--color-on-primary);
|
||||
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-container) 100%);
|
||||
box-shadow: 0 0 32px -4px rgba(0, 191, 165, 0.2);
|
||||
}
|
||||
|
||||
.button.button--secondary {
|
||||
border: 1px solid rgba(15, 81, 76, 0.4);
|
||||
color: var(--color-on-surface);
|
||||
background: rgba(0, 30, 28, 0.65);
|
||||
}
|
||||
|
||||
.button.button--secondary:hover,
|
||||
.button.button--primary:hover {
|
||||
transform: translateY(-1px);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.mod-release-card {
|
||||
background: linear-gradient(180deg, rgba(0, 30, 28, 0.85) 0%, rgba(0, 17, 16, 0.92) 100%);
|
||||
border-radius: 0.8rem;
|
||||
box-shadow: inset 0 0 0 1px rgba(15, 81, 76, 0.12), 0 12px 24px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.mod-release-badge {
|
||||
color: var(--color-primary);
|
||||
background: var(--color-surface-container-high);
|
||||
border-radius: 999px;
|
||||
padding: 0.24rem 0.62rem;
|
||||
font-size: 0.74rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.mod-release-btn-primary {
|
||||
color: var(--color-on-primary);
|
||||
font-weight: 700;
|
||||
border-radius: 0.6rem;
|
||||
padding: 0.52rem 1rem;
|
||||
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-container));
|
||||
box-shadow: 0 0 24px rgba(97, 244, 216, 0.15);
|
||||
}
|
||||
|
||||
.mod-release-btn-outline {
|
||||
color: var(--color-on-surface);
|
||||
font-weight: 700;
|
||||
border-radius: 0.6rem;
|
||||
padding: 0.52rem 1rem;
|
||||
background: rgba(0, 30, 28, 0.7);
|
||||
box-shadow: inset 0 0 0 1px rgba(15, 81, 76, 0.35);
|
||||
}
|
||||
|
||||
.mod-release-btn-primary:hover,
|
||||
.mod-release-btn-outline:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media (max-width: 996px) {
|
||||
.navbar {
|
||||
-webkit-backdrop-filter: blur(14px) saturate(130%);
|
||||
backdrop-filter: blur(14px) saturate(130%);
|
||||
}
|
||||
|
||||
.hero-orb {
|
||||
opacity: 0.28;
|
||||
}
|
||||
|
||||
.menu__link {
|
||||
border-radius: 0.45rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Optional: Material Symbols (loaded via docusaurus.config.js headTags) */
|
||||
.material-symbols-outlined {
|
||||
font-family: "Material Symbols Outlined", sans-serif;
|
||||
font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24;
|
||||
font-style: normal;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
}
|
||||
173
src/data/moduleCatalog.ts
Normal file
173
src/data/moduleCatalog.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
export type ModuleType = 'plugin' | 'mod';
|
||||
|
||||
export type ModuleEntry = {
|
||||
id: string;
|
||||
name: string;
|
||||
type: ModuleType;
|
||||
description: string;
|
||||
version: string;
|
||||
author: string;
|
||||
languages: string[];
|
||||
dependencies: string[];
|
||||
wikiPath: string;
|
||||
releasePath: string;
|
||||
downloadPath: string;
|
||||
releaseReady: boolean;
|
||||
};
|
||||
|
||||
export const moduleCatalog: ModuleEntry[] = [
|
||||
{
|
||||
id: 'ffm-plugin-asset-exporter',
|
||||
name: 'FFM.Plugin.AssetExporter',
|
||||
type: 'plugin',
|
||||
description: 'Export-focused asset tooling for Data Center workflows.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'FrikaMF'],
|
||||
wikiPath: '/wiki/mods/extensions/ffm-plugin-asset-exporter',
|
||||
releasePath: '/wiki/releases/plugins/ffm-plugin-asset-exporter-release',
|
||||
downloadPath: '/plugin/FFM.Plugin.AssetExporter.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'ffm-plugin-multiplayer',
|
||||
name: 'FFM.Plugin.Multiplayer',
|
||||
type: 'plugin',
|
||||
description: 'Multiplayer-oriented plugin surface for FrikaMF ecosystems.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'FrikaMF'],
|
||||
wikiPath: '/wiki/mods/extensions/ffm-plugin-multiplayer',
|
||||
releasePath: '/wiki/releases/plugins/ffm-plugin-multiplayer-release',
|
||||
downloadPath: '/plugin/FFM.Plugin.Multiplayer.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'ffm-plugin-player-models',
|
||||
name: 'FFM.Plugin.PlayerModels',
|
||||
type: 'plugin',
|
||||
description: 'Player model extension plugin for runtime and presentation logic.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'FrikaMF'],
|
||||
wikiPath: '/wiki/mods/extensions/ffm-plugin-player-models',
|
||||
releasePath: '/wiki/releases/plugins/ffm-plugin-player-models-release',
|
||||
downloadPath: '/plugin/FFM.Plugin.PlayerModels.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'ffm-plugin-sysadmin',
|
||||
name: 'FFM.Plugin.Sysadmin',
|
||||
type: 'plugin',
|
||||
description: 'Sysadmin utility plugin for diagnostics and operations.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'FrikaMF'],
|
||||
wikiPath: '/wiki/mods/extensions/ffm-plugin-sysadmin',
|
||||
releasePath: '/wiki/releases/plugins/ffm-plugin-sysadmin-release',
|
||||
downloadPath: '/plugin/FFM.Plugin.Sysadmin.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'ffm-plugin-web-ui-bridge',
|
||||
name: 'FFM.Plugin.WebUIBridge',
|
||||
type: 'plugin',
|
||||
description: 'Bridge plugin between game runtime data and web UI overlays.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'FrikaMF'],
|
||||
wikiPath: '/wiki/mods/extensions/ffm-plugin-web-ui-bridge',
|
||||
releasePath: '/wiki/releases/plugins/ffm-plugin-web-ui-bridge-release',
|
||||
downloadPath: '/plugin/FFM.Plugin.WebUIBridge.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'fmf-modpathredirector',
|
||||
name: 'FMF.ModPathRedirector',
|
||||
type: 'plugin',
|
||||
description: 'MelonLoader plugin: waits for each subscribed Workshop item (Steam + StreamingAssets/Mods/workshop_*) before MelonMods load.',
|
||||
version: '1.5.0',
|
||||
author: 'DataCenterExporter / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'Steam client'],
|
||||
wikiPath: '/wiki/workshop-uploader',
|
||||
releasePath: '/wiki/releases/plugins/fmf-modpathredirector-release',
|
||||
downloadPath: '/plugin/FMF.ModPathRedirector.dll',
|
||||
releaseReady: true,
|
||||
},
|
||||
{
|
||||
id: 'fmf-console-input-guard',
|
||||
name: 'FMF.ConsoleInputGuard',
|
||||
type: 'mod',
|
||||
description: 'Console interaction guardrails for safer gameplay input handling.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'Harmony'],
|
||||
wikiPath: '/wiki/mods/mods/fmf-console-input-guard',
|
||||
releasePath: '/wiki/releases/mods/fmf-console-input-guard-release',
|
||||
downloadPath: '/mod/FMF.ConsoleInputGuard.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'fmf-gregify-employees',
|
||||
name: 'FMF.GregifyEmployees',
|
||||
type: 'mod',
|
||||
description: 'Gameplay mod for employee theming and behavior customization.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'Harmony'],
|
||||
wikiPath: '/wiki/mods/mods/fmf-gregify-employees',
|
||||
releasePath: '/wiki/releases/mods/fmf-gregify-employees-release',
|
||||
downloadPath: '/mod/FMF.GregifyEmployees.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'fmf-hex-label-mod',
|
||||
name: 'FMF.HexLabelMod',
|
||||
type: 'mod',
|
||||
description: 'In-world hex color labels for cable spinners and racks.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'Harmony'],
|
||||
wikiPath: '/wiki/mods/extensions/fmf-hex-label-mod',
|
||||
releasePath: '/wiki/releases/mods/fmf-hex-label-mod-release',
|
||||
downloadPath: '/mod/FMF.HexLabelMod.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'fmf-lang-compat-bridge',
|
||||
name: 'FMF.LangCompatBridge',
|
||||
type: 'mod',
|
||||
description: 'Localization compatibility bridge for mixed mod stacks.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader'],
|
||||
wikiPath: '/wiki/mods/extensions/fmf-lang-compat-bridge',
|
||||
releasePath: '/wiki/releases/mods/fmf-lang-compat-bridge-release',
|
||||
downloadPath: '/mod/FMF.JoniMLCompatMod.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
{
|
||||
id: 'fmf-ui-replacement-mod',
|
||||
name: 'FMF.UIReplacementMod',
|
||||
type: 'mod',
|
||||
description: 'Replaces and modernizes selected in-game UI layers.',
|
||||
version: 'NotReleasedYet',
|
||||
author: 'mleem97 / FrikaMF Community',
|
||||
languages: ['C#'],
|
||||
dependencies: ['MelonLoader', 'Harmony'],
|
||||
wikiPath: '/wiki/mods/extensions/fmf-ui-replacement-mod',
|
||||
releasePath: '/wiki/releases/mods/fmf-ui-replacement-mod-release',
|
||||
downloadPath: '/mod/FMF.UIReplacementMod.dll',
|
||||
releaseReady: false,
|
||||
},
|
||||
];
|
||||
52
src/i18n/homepage/de.ts
Normal file
52
src/i18n/homepage/de.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { HomepageContent } from './types';
|
||||
|
||||
export const de: HomepageContent = {
|
||||
heroLine1: 'DATACENTER MODDING HUB.',
|
||||
heroLine2: 'SEI SMART WIE GREG.',
|
||||
heroSub1: 'Klar. Flexibel. Community-getrieben.',
|
||||
heroSub2: 'Mit FrikaMF, Rust-Stacks, Multiplayer und Plugins.',
|
||||
ctaStart: 'MODDING STARTEN',
|
||||
ctaMods: 'VERFÜGBARE STANDALONE MODS & PLUGINS',
|
||||
docsPaths: 'Dokumentationspfade',
|
||||
featureTitles: ['Dual-Track Modding', 'Runtime Hook Bridge', 'Wiki-basierte Doku', 'Community-Ökosystem'],
|
||||
featureDescriptions: [
|
||||
'Baue Mods direkt in C# oder nativ in Rust via C-ABI/FFI.',
|
||||
'Harmony-Patches, Event-IDs und deterministische Hook-Weiterleitung.',
|
||||
'Source of truth aus .wiki mit Enduser- und Moddev-Pfaden.',
|
||||
'Core-Framework-Doku plus Standalone-Plugin- und Ökosystem-Doku.',
|
||||
],
|
||||
comingSoon: 'Kommt bald',
|
||||
comingSoonText: '`datacentermods.com` wird gerade vorbereitet. Bis zum Launch findest du alles unter `Docs Hub → Standalone Mods`.',
|
||||
communityTitle: 'Community & Maintainer',
|
||||
communityText: 'Dieses Portal bündelt Framework-Doku und Community-Plugins für das Data-Center-Ökosystem.',
|
||||
docsEndUserTitle: 'Endnutzer',
|
||||
docsEndUserDescription: 'Installation, Updates, FAQ und Fehlerbehebung.',
|
||||
docsModDevsTitle: 'Mod-Entwickler',
|
||||
docsModDevsDescription: 'Debug-Workflows, Setup, Hooks und Referenzen.',
|
||||
docsContributorsTitle: 'Mitwirkende',
|
||||
docsContributorsDescription: 'Konventionen, CI-Checks und Contribution-Workflow.',
|
||||
docsCapabilityTitle: 'Capability Matrix',
|
||||
docsCapabilityDescription: 'Komplette Feature-Übersicht und konkrete Use Cases.',
|
||||
ecosystemTitle: 'Ecosystem Coverage',
|
||||
ecosystemCoreTitle: 'FrikaMF Core',
|
||||
ecosystemCoreDescription: 'Hook-System, FFI-Bridge, Event-Verträge und Runtime-Architektur.',
|
||||
ecosystemCoreCta: 'Core-Doku öffnen →',
|
||||
ecosystemRustTitle: 'Standalone Rust',
|
||||
ecosystemRustDescription: 'Rust/FFI-Implementierungsleitfäden für externe und standalone Runtimes.',
|
||||
ecosystemRustCta: 'Rust/FFI-Doku öffnen →',
|
||||
ecosystemMultiplayerTitle: 'Multiplayer & Plugins',
|
||||
ecosystemMultiplayerDescription: 'Multiplayer-Roadmap, Plugin-Doku und Community-Modul-Referenzen.',
|
||||
ecosystemMultiplayerCta: 'Multiplayer-Doku öffnen →',
|
||||
gregTitle: 'Die Legende von Greg',
|
||||
gregText1:
|
||||
'Greg ist der unermüdliche Server-Techniker des Projekts. Er wirkt zwar so, als hätte er seit Monaten nicht mehr geschlafen, und er ist meistens still — aber sobald ein Rack ausfällt oder ein Mod zickt, ist Greg schon da.',
|
||||
gregText2:
|
||||
'Unterwürfig erfüllt er all deine Wünsche: mehr Uptime, sauberere Configs, bessere Logs und weniger Drama im Deployment. Er fragt nicht viel, er liefert einfach.',
|
||||
gregQuote: '"Be smart. Be like Greg."',
|
||||
supportTitle: 'Support',
|
||||
supportText: 'Melde Bugs, fordere Doku für neue Community-Plugins an und verfolge Workstreams.',
|
||||
supportCta: 'GitHub Issues öffnen',
|
||||
availableModsLabel: 'Verfügbare Mods',
|
||||
repositoryLabel: 'Repository',
|
||||
joinLabel: 'BEITRETEN',
|
||||
};
|
||||
52
src/i18n/homepage/en.ts
Normal file
52
src/i18n/homepage/en.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { HomepageContent } from './types';
|
||||
|
||||
export const en: HomepageContent = {
|
||||
heroLine1: 'DATACENTER MODDING HUB.',
|
||||
heroLine2: 'SMART LIKE GREG.',
|
||||
heroSub1: 'Streamlined. Flexible. Community-curated.',
|
||||
heroSub2: 'Covering FrikaMF, Rust stacks, multiplayer and plugins.',
|
||||
ctaStart: 'START MODDING',
|
||||
ctaMods: 'AVAILABLE STANDALONE MODS & PLUGINS',
|
||||
docsPaths: 'Documentation Paths',
|
||||
featureTitles: ['Dual-Track Modding', 'Runtime Hook Bridge', 'Wiki-Driven Docs', 'Community Ecosystem'],
|
||||
featureDescriptions: [
|
||||
'Build mods in C# directly or native in Rust via C-ABI/FFI.',
|
||||
'Harmony patches, event IDs, and deterministic hook forwarding.',
|
||||
'Source of truth from .wiki with end-user and mod-dev paths.',
|
||||
'Core framework docs plus standalone plugin and ecosystem docs.',
|
||||
],
|
||||
comingSoon: 'Coming Soon',
|
||||
comingSoonText: '`datacentermods.com` is currently in preparation. Until launch, use `Docs Hub → Standalone Mods`.',
|
||||
communityTitle: 'Community & Maintainers',
|
||||
communityText: 'This portal is designed for framework docs and community-built plugins across the Data Center ecosystem.',
|
||||
docsEndUserTitle: 'End-User',
|
||||
docsEndUserDescription: 'Install, update, FAQ, troubleshooting.',
|
||||
docsModDevsTitle: 'Mod-Devs',
|
||||
docsModDevsDescription: 'Debug workflows, setup, hooks and references.',
|
||||
docsContributorsTitle: 'Contributors',
|
||||
docsContributorsDescription: 'Conventions, CI checks, contribution workflow.',
|
||||
docsCapabilityTitle: 'Capability Matrix',
|
||||
docsCapabilityDescription: 'Complete feature map and implementation use cases.',
|
||||
ecosystemTitle: 'Ecosystem Coverage',
|
||||
ecosystemCoreTitle: 'FrikaMF Core',
|
||||
ecosystemCoreDescription: 'Hook system, FFI bridge, event contracts and runtime architecture.',
|
||||
ecosystemCoreCta: 'Open core docs →',
|
||||
ecosystemRustTitle: 'Standalone Rust',
|
||||
ecosystemRustDescription: 'Rust/FFI implementation guides for external and standalone runtimes.',
|
||||
ecosystemRustCta: 'Open Rust/FFI docs →',
|
||||
ecosystemMultiplayerTitle: 'Multiplayer & Plugins',
|
||||
ecosystemMultiplayerDescription: 'Multiplayer roadmap, plugin docs, and community module references.',
|
||||
ecosystemMultiplayerCta: 'Open multiplayer docs →',
|
||||
gregTitle: 'The Legend of Greg',
|
||||
gregText1:
|
||||
'Greg is the tireless server technician of this project. He looks like he has not slept for months, and he is usually quiet — but once a rack fails or a mod breaks, Greg is already there.',
|
||||
gregText2:
|
||||
'He quietly fulfills your wishes: more uptime, cleaner configs, better logs and less deployment drama. He does not ask much, he just ships.',
|
||||
gregQuote: '"Be smart. Be like Greg."',
|
||||
supportTitle: 'Support',
|
||||
supportText: 'Report bugs, request docs for new community plugins, and track workstreams.',
|
||||
supportCta: 'Open GitHub Issues',
|
||||
availableModsLabel: 'Available Mods',
|
||||
repositoryLabel: 'Repository',
|
||||
joinLabel: 'JOIN',
|
||||
};
|
||||
52
src/i18n/homepage/es.ts
Normal file
52
src/i18n/homepage/es.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { HomepageContent } from './types';
|
||||
|
||||
export const es: HomepageContent = {
|
||||
heroLine1: 'HUB DE MODDING DATACENTER.',
|
||||
heroLine2: 'SÉ INTELIGENTE. SÉ COMO GREG.',
|
||||
heroSub1: 'Claro. Flexible. Impulsado por la comunidad.',
|
||||
heroSub2: 'Con FrikaMF, stacks Rust, multijugador y plugins.',
|
||||
ctaStart: 'EMPEZAR MODDING',
|
||||
ctaMods: 'MODS Y PLUGINS STANDALONE DISPONIBLES',
|
||||
docsPaths: 'Rutas de documentación',
|
||||
featureTitles: ['Modding doble vía', 'Puente de hooks runtime', 'Docs desde wiki', 'Ecosistema comunidad'],
|
||||
featureDescriptions: [
|
||||
'Crea mods en C# o en Rust nativo vía C-ABI/FFI.',
|
||||
'Parches Harmony, IDs de eventos y forwarding determinista.',
|
||||
'Fuente oficial en .wiki para usuarios y modders.',
|
||||
'Docs del framework core y de plugins standalone.',
|
||||
],
|
||||
comingSoon: 'Próximamente',
|
||||
comingSoonText: '`datacentermods.com` está en preparación. Mientras tanto, usa `Docs Hub → Standalone Mods`.',
|
||||
communityTitle: 'Comunidad y mantenedores',
|
||||
communityText: 'Este portal reúne docs del framework y plugins de la comunidad para el ecosistema Data Center.',
|
||||
docsEndUserTitle: 'End-User',
|
||||
docsEndUserDescription: 'Install, update, FAQ, troubleshooting.',
|
||||
docsModDevsTitle: 'Mod-Devs',
|
||||
docsModDevsDescription: 'Debug workflows, setup, hooks and references.',
|
||||
docsContributorsTitle: 'Contributors',
|
||||
docsContributorsDescription: 'Conventions, CI checks, contribution workflow.',
|
||||
docsCapabilityTitle: 'Capability Matrix',
|
||||
docsCapabilityDescription: 'Complete feature map and implementation use cases.',
|
||||
ecosystemTitle: 'Ecosystem Coverage',
|
||||
ecosystemCoreTitle: 'FrikaMF Core',
|
||||
ecosystemCoreDescription: 'Hook system, FFI bridge, event contracts and runtime architecture.',
|
||||
ecosystemCoreCta: 'Open core docs →',
|
||||
ecosystemRustTitle: 'Standalone Rust',
|
||||
ecosystemRustDescription: 'Rust/FFI implementation guides for external and standalone runtimes.',
|
||||
ecosystemRustCta: 'Open Rust/FFI docs →',
|
||||
ecosystemMultiplayerTitle: 'Multiplayer & Plugins',
|
||||
ecosystemMultiplayerDescription: 'Multiplayer roadmap, plugin docs, and community module references.',
|
||||
ecosystemMultiplayerCta: 'Open multiplayer docs →',
|
||||
gregTitle: 'The Legend of Greg',
|
||||
gregText1:
|
||||
'Greg is the tireless server technician of this project. He looks like he has not slept for months, and he is usually quiet — but once a rack fails or a mod breaks, Greg is already there.',
|
||||
gregText2:
|
||||
'He quietly fulfills your wishes: more uptime, cleaner configs, better logs and less deployment drama. He does not ask much, he just ships.',
|
||||
gregQuote: '"Be smart. Be like Greg."',
|
||||
supportTitle: 'Support',
|
||||
supportText: 'Report bugs, request docs for new community plugins, and track workstreams.',
|
||||
supportCta: 'Open GitHub Issues',
|
||||
availableModsLabel: 'Available Mods',
|
||||
repositoryLabel: 'Repository',
|
||||
joinLabel: 'JOIN',
|
||||
};
|
||||
52
src/i18n/homepage/fr.ts
Normal file
52
src/i18n/homepage/fr.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { HomepageContent } from './types';
|
||||
|
||||
export const fr: HomepageContent = {
|
||||
heroLine1: 'HUB DE MODDING DATACENTER.',
|
||||
heroLine2: 'SOYEZ MALIN, SOYEZ GREG.',
|
||||
heroSub1: 'Simple. Flexible. Piloté par la communauté.',
|
||||
heroSub2: 'FrikaMF, stacks Rust, multijoueur et plugins.',
|
||||
ctaStart: 'COMMENCER LE MODDING',
|
||||
ctaMods: 'MODS & PLUGINS STANDALONE DISPONIBLES',
|
||||
docsPaths: 'Parcours de documentation',
|
||||
featureTitles: ['Modding double piste', 'Pont runtime hooks', 'Docs basées sur le wiki', 'Écosystème communauté'],
|
||||
featureDescriptions: [
|
||||
'Créez des mods en C# ou en Rust natif via C-ABI/FFI.',
|
||||
'Patches Harmony, IDs d’événements et routage déterministe.',
|
||||
'Source de vérité issue de .wiki pour users et moddeurs.',
|
||||
'Docs du framework principal et des plugins standalone.',
|
||||
],
|
||||
comingSoon: 'Bientôt disponible',
|
||||
comingSoonText: '`datacentermods.com` est en préparation. En attendant, consultez `Docs Hub → Standalone Mods`.',
|
||||
communityTitle: 'Communauté & Mainteneurs',
|
||||
communityText: 'Ce portail regroupe la doc framework et les plugins communautaires de l’écosystème Data Center.',
|
||||
docsEndUserTitle: 'End-User',
|
||||
docsEndUserDescription: 'Install, update, FAQ, troubleshooting.',
|
||||
docsModDevsTitle: 'Mod-Devs',
|
||||
docsModDevsDescription: 'Debug workflows, setup, hooks and references.',
|
||||
docsContributorsTitle: 'Contributors',
|
||||
docsContributorsDescription: 'Conventions, CI checks, contribution workflow.',
|
||||
docsCapabilityTitle: 'Capability Matrix',
|
||||
docsCapabilityDescription: 'Complete feature map and implementation use cases.',
|
||||
ecosystemTitle: 'Ecosystem Coverage',
|
||||
ecosystemCoreTitle: 'FrikaMF Core',
|
||||
ecosystemCoreDescription: 'Hook system, FFI bridge, event contracts and runtime architecture.',
|
||||
ecosystemCoreCta: 'Open core docs →',
|
||||
ecosystemRustTitle: 'Standalone Rust',
|
||||
ecosystemRustDescription: 'Rust/FFI implementation guides for external and standalone runtimes.',
|
||||
ecosystemRustCta: 'Open Rust/FFI docs →',
|
||||
ecosystemMultiplayerTitle: 'Multiplayer & Plugins',
|
||||
ecosystemMultiplayerDescription: 'Multiplayer roadmap, plugin docs, and community module references.',
|
||||
ecosystemMultiplayerCta: 'Open multiplayer docs →',
|
||||
gregTitle: 'The Legend of Greg',
|
||||
gregText1:
|
||||
'Greg is the tireless server technician of this project. He looks like he has not slept for months, and he is usually quiet — but once a rack fails or a mod breaks, Greg is already there.',
|
||||
gregText2:
|
||||
'He quietly fulfills your wishes: more uptime, cleaner configs, better logs and less deployment drama. He does not ask much, he just ships.',
|
||||
gregQuote: '"Be smart. Be like Greg."',
|
||||
supportTitle: 'Support',
|
||||
supportText: 'Report bugs, request docs for new community plugins, and track workstreams.',
|
||||
supportCta: 'Open GitHub Issues',
|
||||
availableModsLabel: 'Available Mods',
|
||||
repositoryLabel: 'Repository',
|
||||
joinLabel: 'JOIN',
|
||||
};
|
||||
33
src/i18n/homepage/index.ts
Normal file
33
src/i18n/homepage/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { de } from './de';
|
||||
import { en } from './en';
|
||||
import { es } from './es';
|
||||
import { fr } from './fr';
|
||||
import { ja } from './ja';
|
||||
import { ru } from './ru';
|
||||
import type { HomepageContent, LocaleKey } from './types';
|
||||
|
||||
const homepageByLocale: Record<LocaleKey, HomepageContent> = {
|
||||
en,
|
||||
de,
|
||||
fr,
|
||||
es,
|
||||
ru,
|
||||
ja,
|
||||
};
|
||||
|
||||
export type { HomepageContent, LocaleKey } from './types';
|
||||
|
||||
export function getHomepageContent(locale: string): HomepageContent {
|
||||
const normalizedLocale = (locale || 'en').toLowerCase();
|
||||
const languageOnly = normalizedLocale.split('-')[0] as LocaleKey;
|
||||
|
||||
if (normalizedLocale in homepageByLocale) {
|
||||
return homepageByLocale[normalizedLocale as LocaleKey];
|
||||
}
|
||||
|
||||
if (languageOnly in homepageByLocale) {
|
||||
return homepageByLocale[languageOnly];
|
||||
}
|
||||
|
||||
return homepageByLocale.en;
|
||||
}
|
||||
52
src/i18n/homepage/ja.ts
Normal file
52
src/i18n/homepage/ja.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { HomepageContent } from './types';
|
||||
|
||||
export const ja: HomepageContent = {
|
||||
heroLine1: 'DATACENTER MODDING HUB.',
|
||||
heroLine2: 'BE SMART. BE LIKE GREG.',
|
||||
heroSub1: 'シンプル。柔軟。コミュニティ主導。',
|
||||
heroSub2: 'FrikaMF、Rustスタック、マルチプレイ、プラグインを網羅。',
|
||||
ctaStart: 'MODDING を始める',
|
||||
ctaMods: '利用可能な STANDALONE MODS & PLUGINS',
|
||||
docsPaths: 'ドキュメント導線',
|
||||
featureTitles: ['デュアルトラック Modding', 'ランタイム Hook Bridge', 'Wiki ベース Docs', 'コミュニティ エコシステム'],
|
||||
featureDescriptions: [
|
||||
'C# または Rust (C-ABI/FFI) で Mod を開発。',
|
||||
'Harmony パッチ、Event ID、決定的な Hook 転送。',
|
||||
'.wiki を source of truth としたユーザー/開発者向け導線。',
|
||||
'Framework 本体と Standalone プラグインの情報を統合。',
|
||||
],
|
||||
comingSoon: '近日公開',
|
||||
comingSoonText: '`datacentermods.com` は準備中です。公開まで `Docs Hub → Standalone Mods` をご利用ください。',
|
||||
communityTitle: 'コミュニティ & メンテナー',
|
||||
communityText: 'このポータルは Data Center エコシステム向けに framework docs と community plugins をまとめています。',
|
||||
docsEndUserTitle: 'End-User',
|
||||
docsEndUserDescription: 'Install, update, FAQ, troubleshooting.',
|
||||
docsModDevsTitle: 'Mod-Devs',
|
||||
docsModDevsDescription: 'Debug workflows, setup, hooks and references.',
|
||||
docsContributorsTitle: 'Contributors',
|
||||
docsContributorsDescription: 'Conventions, CI checks, contribution workflow.',
|
||||
docsCapabilityTitle: 'Capability Matrix',
|
||||
docsCapabilityDescription: 'Complete feature map and implementation use cases.',
|
||||
ecosystemTitle: 'Ecosystem Coverage',
|
||||
ecosystemCoreTitle: 'FrikaMF Core',
|
||||
ecosystemCoreDescription: 'Hook system, FFI bridge, event contracts and runtime architecture.',
|
||||
ecosystemCoreCta: 'Open core docs →',
|
||||
ecosystemRustTitle: 'Standalone Rust',
|
||||
ecosystemRustDescription: 'Rust/FFI implementation guides for external and standalone runtimes.',
|
||||
ecosystemRustCta: 'Open Rust/FFI docs →',
|
||||
ecosystemMultiplayerTitle: 'Multiplayer & Plugins',
|
||||
ecosystemMultiplayerDescription: 'Multiplayer roadmap, plugin docs, and community module references.',
|
||||
ecosystemMultiplayerCta: 'Open multiplayer docs →',
|
||||
gregTitle: 'The Legend of Greg',
|
||||
gregText1:
|
||||
'Greg is the tireless server technician of this project. He looks like he has not slept for months, and he is usually quiet — but once a rack fails or a mod breaks, Greg is already there.',
|
||||
gregText2:
|
||||
'He quietly fulfills your wishes: more uptime, cleaner configs, better logs and less deployment drama. He does not ask much, he just ships.',
|
||||
gregQuote: '"Be smart. Be like Greg."',
|
||||
supportTitle: 'Support',
|
||||
supportText: 'Report bugs, request docs for new community plugins, and track workstreams.',
|
||||
supportCta: 'Open GitHub Issues',
|
||||
availableModsLabel: 'Available Mods',
|
||||
repositoryLabel: 'Repository',
|
||||
joinLabel: 'JOIN',
|
||||
};
|
||||
52
src/i18n/homepage/ru.ts
Normal file
52
src/i18n/homepage/ru.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { HomepageContent } from './types';
|
||||
|
||||
export const ru: HomepageContent = {
|
||||
heroLine1: 'ХАБ МОДДИНГА DATACENTER.',
|
||||
heroLine2: 'БУДЬ УМНЫМ. БУДЬ КАК ГРЕГ.',
|
||||
heroSub1: 'Просто. Гибко. Силой сообщества.',
|
||||
heroSub2: 'FrikaMF, Rust-стек, мультиплеер и плагины.',
|
||||
ctaStart: 'НАЧАТЬ МОДДИНГ',
|
||||
ctaMods: 'ДОСТУПНЫЕ STANDALONE МОДЫ И ПЛАГИНЫ',
|
||||
docsPaths: 'Разделы документации',
|
||||
featureTitles: ['Два пути моддинга', 'Runtime Hook Bridge', 'Вики-документация', 'Экосистема сообщества'],
|
||||
featureDescriptions: [
|
||||
'Пишите моды на C# или нативно на Rust через C-ABI/FFI.',
|
||||
'Harmony-патчи, event IDs и детерминированный forwarding.',
|
||||
'Единый источник в .wiki для пользователей и моддеров.',
|
||||
'Документация ядра и standalone-плагинов сообщества.',
|
||||
],
|
||||
comingSoon: 'Скоро',
|
||||
comingSoonText: '`datacentermods.com` пока готовится. До запуска используйте `Docs Hub → Standalone Mods`.',
|
||||
communityTitle: 'Сообщество и мейнтейнеры',
|
||||
communityText: 'Портал объединяет документацию фреймворка и community-плагинов экосистемы Data Center.',
|
||||
docsEndUserTitle: 'End-User',
|
||||
docsEndUserDescription: 'Install, update, FAQ, troubleshooting.',
|
||||
docsModDevsTitle: 'Mod-Devs',
|
||||
docsModDevsDescription: 'Debug workflows, setup, hooks and references.',
|
||||
docsContributorsTitle: 'Contributors',
|
||||
docsContributorsDescription: 'Conventions, CI checks, contribution workflow.',
|
||||
docsCapabilityTitle: 'Capability Matrix',
|
||||
docsCapabilityDescription: 'Complete feature map and implementation use cases.',
|
||||
ecosystemTitle: 'Ecosystem Coverage',
|
||||
ecosystemCoreTitle: 'FrikaMF Core',
|
||||
ecosystemCoreDescription: 'Hook system, FFI bridge, event contracts and runtime architecture.',
|
||||
ecosystemCoreCta: 'Open core docs →',
|
||||
ecosystemRustTitle: 'Standalone Rust',
|
||||
ecosystemRustDescription: 'Rust/FFI implementation guides for external and standalone runtimes.',
|
||||
ecosystemRustCta: 'Open Rust/FFI docs →',
|
||||
ecosystemMultiplayerTitle: 'Multiplayer & Plugins',
|
||||
ecosystemMultiplayerDescription: 'Multiplayer roadmap, plugin docs, and community module references.',
|
||||
ecosystemMultiplayerCta: 'Open multiplayer docs →',
|
||||
gregTitle: 'The Legend of Greg',
|
||||
gregText1:
|
||||
'Greg is the tireless server technician of this project. He looks like he has not slept for months, and he is usually quiet — but once a rack fails or a mod breaks, Greg is already there.',
|
||||
gregText2:
|
||||
'He quietly fulfills your wishes: more uptime, cleaner configs, better logs and less deployment drama. He does not ask much, he just ships.',
|
||||
gregQuote: '"Be smart. Be like Greg."',
|
||||
supportTitle: 'Support',
|
||||
supportText: 'Report bugs, request docs for new community plugins, and track workstreams.',
|
||||
supportCta: 'Open GitHub Issues',
|
||||
availableModsLabel: 'Available Mods',
|
||||
repositoryLabel: 'Repository',
|
||||
joinLabel: 'JOIN',
|
||||
};
|
||||
45
src/i18n/homepage/types.ts
Normal file
45
src/i18n/homepage/types.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
export type LocaleKey = 'en' | 'de' | 'fr' | 'es' | 'ru' | 'ja';
|
||||
|
||||
export type HomepageContent = {
|
||||
heroLine1: string;
|
||||
heroLine2: string;
|
||||
heroSub1: string;
|
||||
heroSub2: string;
|
||||
ctaStart: string;
|
||||
ctaMods: string;
|
||||
docsPaths: string;
|
||||
featureTitles: [string, string, string, string];
|
||||
featureDescriptions: [string, string, string, string];
|
||||
comingSoon: string;
|
||||
comingSoonText: string;
|
||||
communityTitle: string;
|
||||
communityText: string;
|
||||
docsEndUserTitle: string;
|
||||
docsEndUserDescription: string;
|
||||
docsModDevsTitle: string;
|
||||
docsModDevsDescription: string;
|
||||
docsContributorsTitle: string;
|
||||
docsContributorsDescription: string;
|
||||
docsCapabilityTitle: string;
|
||||
docsCapabilityDescription: string;
|
||||
ecosystemTitle: string;
|
||||
ecosystemCoreTitle: string;
|
||||
ecosystemCoreDescription: string;
|
||||
ecosystemCoreCta: string;
|
||||
ecosystemRustTitle: string;
|
||||
ecosystemRustDescription: string;
|
||||
ecosystemRustCta: string;
|
||||
ecosystemMultiplayerTitle: string;
|
||||
ecosystemMultiplayerDescription: string;
|
||||
ecosystemMultiplayerCta: string;
|
||||
gregTitle: string;
|
||||
gregText1: string;
|
||||
gregText2: string;
|
||||
gregQuote: string;
|
||||
supportTitle: string;
|
||||
supportText: string;
|
||||
supportCta: string;
|
||||
availableModsLabel: string;
|
||||
repositoryLabel: string;
|
||||
joinLabel: string;
|
||||
};
|
||||
BIN
src/image.png
Normal file
BIN
src/image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 289 KiB |
368
src/pages/index.tsx
Normal file
368
src/pages/index.tsx
Normal file
@@ -0,0 +1,368 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import { motion, type Variants, useReducedMotion } from 'framer-motion';
|
||||
import { getHomepageContent } from '../i18n/homepage';
|
||||
import gregImage from '../image.png';
|
||||
import {
|
||||
FaArrowUpRightFromSquare,
|
||||
FaBookOpen,
|
||||
FaCode,
|
||||
FaDiscord,
|
||||
FaGithub,
|
||||
FaLifeRing,
|
||||
FaPeopleGroup,
|
||||
FaShop,
|
||||
FaScrewdriverWrench,
|
||||
} from 'react-icons/fa6';
|
||||
|
||||
type FeatureItem = {
|
||||
icon: React.ReactNode;
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
type DocPathItem = {
|
||||
title: string;
|
||||
description: string;
|
||||
link: string;
|
||||
};
|
||||
|
||||
const viewport = { once: true, margin: '-90px' };
|
||||
|
||||
function buildVariants(reducedMotion: boolean) {
|
||||
const section: Variants = reducedMotion
|
||||
? { hidden: { opacity: 0 }, show: { opacity: 1 } }
|
||||
: {
|
||||
hidden: { opacity: 0, y: 26 },
|
||||
show: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.65, ease: [0.16, 1, 0.3, 1] },
|
||||
},
|
||||
};
|
||||
|
||||
const grid: Variants = {
|
||||
hidden: {},
|
||||
show: {
|
||||
transition: {
|
||||
staggerChildren: reducedMotion ? 0 : 0.09,
|
||||
delayChildren: reducedMotion ? 0 : 0.06,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const card: Variants = reducedMotion
|
||||
? { hidden: { opacity: 0 }, show: { opacity: 1 } }
|
||||
: {
|
||||
hidden: { opacity: 0, y: 18, scale: 0.98 },
|
||||
show: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
scale: 1,
|
||||
transition: { duration: 0.45, ease: [0.16, 1, 0.3, 1] },
|
||||
},
|
||||
};
|
||||
|
||||
const textReveal: Variants = reducedMotion
|
||||
? { hidden: { opacity: 0 }, show: { opacity: 1 } }
|
||||
: {
|
||||
hidden: { opacity: 0, y: 18 },
|
||||
show: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.5, ease: [0.16, 1, 0.3, 1] },
|
||||
},
|
||||
};
|
||||
|
||||
return { section, grid, card, textReveal };
|
||||
}
|
||||
|
||||
export default function HomePage(): JSX.Element {
|
||||
const {
|
||||
i18n: { currentLocale },
|
||||
} = useDocusaurusContext();
|
||||
|
||||
const t = getHomepageContent(currentLocale);
|
||||
const reducedMotion = useReducedMotion();
|
||||
const variants = useMemo(() => buildVariants(Boolean(reducedMotion)), [reducedMotion]);
|
||||
|
||||
const features: FeatureItem[] = [
|
||||
{
|
||||
icon: <FaScrewdriverWrench className="text-xl" />,
|
||||
title: t.featureTitles[0],
|
||||
description: t.featureDescriptions[0],
|
||||
},
|
||||
{
|
||||
icon: <FaCode className="text-xl" />,
|
||||
title: t.featureTitles[1],
|
||||
description: t.featureDescriptions[1],
|
||||
},
|
||||
{
|
||||
icon: <FaBookOpen className="text-xl" />,
|
||||
title: t.featureTitles[2],
|
||||
description: t.featureDescriptions[2],
|
||||
},
|
||||
{
|
||||
icon: <FaPeopleGroup className="text-xl" />,
|
||||
title: t.featureTitles[3],
|
||||
description: t.featureDescriptions[3],
|
||||
},
|
||||
];
|
||||
|
||||
const knowledgePaths: DocPathItem[] = [
|
||||
{ title: 'Wiki Overview', description: 'Canonical docs entrypoint under /wiki.', link: '/wiki' },
|
||||
{ title: 'Framework Core', description: 'Runtime hooks, bridge, events and architecture.', link: '/wiki/mods/framework' },
|
||||
{ title: 'Plugin Wiki', description: 'Plugin-specific docs and release pages.', link: '/wiki/mods/extensions/' },
|
||||
{ title: 'Mod Wiki', description: 'Gameplay mods, release state and module docs.', link: '/wiki/mods/mods' },
|
||||
{ title: 'FMF Hooks Catalog', description: 'Auto-generated hook strings and event-id map from framework sources.', link: '/wiki/reference/fmf-hooks-catalog' },
|
||||
{ title: 'Release Channels', description: 'Steam Workshop for discovery; GitHub for beta and alternate DLLs.', link: '/wiki/reference/release-channels' },
|
||||
{ title: 'Unified Roadmap', description: 'Consolidated roadmap with duplicate tracks removed.', link: '/wiki/roadmap/unified-roadmap' },
|
||||
{ title: 'Mods Catalog', description: 'Dynamic /mods catalog with wiki and download links.', link: '/mods' },
|
||||
];
|
||||
|
||||
const workflowPaths: DocPathItem[] = [
|
||||
{ title: 'End-User Docs', description: 'Install, update and troubleshooting paths.', link: '/wiki/wiki-import/EndUser/End-User-Release' },
|
||||
{ title: 'Mod Developer Docs', description: 'Setup, debug and hook integration guides.', link: '/wiki/wiki-import/ModDevs/Mod-Developer-Debug' },
|
||||
{ title: 'Repo Inventory', description: 'Monorepo layout, projects, and solution drift for contributors.', link: '/wiki/contributors/repo-inventory' },
|
||||
{ title: 'Contributor Workflow', description: 'Contribution standards and repository workflow.', link: '/wiki/contributors/docusaurus-workflow' },
|
||||
{ title: 'Plugin Security Audit', description: 'Git-link submission and malicious-code audit process.', link: '/wiki/contributors/plugin-submission-audit' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Layout
|
||||
description="Community docs for FrikaMF, standalone Rust stacks, multiplayer, and plugins.">
|
||||
<main className="bg-background text-on-surface font-sans min-h-screen editorial-bleed bg-hero-gradient">
|
||||
<section className="hero-motion-wrap relative flex min-h-[68vh] flex-col items-center justify-center overflow-hidden px-4 py-20 text-center">
|
||||
<div className="hero-particles" aria-hidden="true" />
|
||||
<div className="hero-orb hero-orb-pink" aria-hidden="true" />
|
||||
<div className="hero-orb hero-orb-green" aria-hidden="true" />
|
||||
|
||||
<motion.h1
|
||||
className="homepage-logo-title text-reveal-glow mb-8 text-4xl font-black leading-none tracking-tight text-on-surface md:text-6xl"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.textReveal}>
|
||||
FRIKA MOD <span className="text-primary">🍪</span>
|
||||
<br />
|
||||
<span className="text-gradient-brand">FRAMEWORK</span>
|
||||
</motion.h1>
|
||||
|
||||
<motion.h2
|
||||
className="mb-4 max-w-3xl font-headline text-2xl font-bold tracking-tight text-on-surface md:text-4xl"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.textReveal}
|
||||
transition={{ delay: reducedMotion ? 0 : 0.08 }}>
|
||||
{t.heroLine1}
|
||||
<br />
|
||||
<span className="text-on-surface-variant">{t.heroLine2}</span>
|
||||
</motion.h2>
|
||||
|
||||
<motion.p
|
||||
className="mb-10 max-w-lg text-base font-medium text-on-surface-variant md:text-lg"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.textReveal}
|
||||
transition={{ delay: reducedMotion ? 0 : 0.14 }}>
|
||||
{t.heroSub1}
|
||||
<br />
|
||||
{t.heroSub2}
|
||||
</motion.p>
|
||||
|
||||
<motion.div
|
||||
className="flex flex-wrap items-center justify-center gap-3"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.textReveal}
|
||||
transition={{ delay: reducedMotion ? 0 : 0.22 }}>
|
||||
<Link to="/wiki/mods/framework" className="btn-primary hero-glow px-8 py-4 rounded-xl text-lg">
|
||||
{t.ctaStart}
|
||||
</Link>
|
||||
<Link to="/mods" className="btn-outline px-8 py-4 rounded-xl text-lg">
|
||||
{t.ctaMods}
|
||||
</Link>
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
<motion.section
|
||||
id="features"
|
||||
className="section-surface-alt px-4 py-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.section}>
|
||||
<motion.div className="mx-auto grid max-w-6xl grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4" variants={variants.grid}>
|
||||
{features.map((feature) => (
|
||||
<motion.article
|
||||
key={feature.title}
|
||||
className="app-card app-card-motion app-card-glow glass-card p-5 rounded-xl text-on-surface"
|
||||
variants={variants.card}
|
||||
whileHover={
|
||||
reducedMotion
|
||||
? undefined
|
||||
: {
|
||||
y: -6,
|
||||
rotateX: 2,
|
||||
rotateY: -2,
|
||||
scale: 1.01,
|
||||
transition: { type: 'spring', stiffness: 280, damping: 18 },
|
||||
}
|
||||
}
|
||||
style={{ transformStyle: 'preserve-3d' }}>
|
||||
<h3 className="mb-2 flex items-center gap-2 font-headline text-lg font-bold text-on-surface">
|
||||
<span className="text-primary">{feature.icon}</span>
|
||||
<span>{feature.title}</span>
|
||||
</h3>
|
||||
<p className="text-sm font-medium text-on-surface-variant">{feature.description}</p>
|
||||
</motion.article>
|
||||
))}
|
||||
</motion.div>
|
||||
</motion.section>
|
||||
|
||||
<motion.section
|
||||
id="docs"
|
||||
className="px-4 py-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.section}>
|
||||
<div className="mx-auto max-w-5xl text-center">
|
||||
<motion.h2 className="mb-10 font-headline text-3xl font-bold text-on-surface" variants={variants.textReveal}>
|
||||
Knowledge Architecture
|
||||
</motion.h2>
|
||||
<motion.div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3" variants={variants.grid}>
|
||||
{knowledgePaths.map((doc) => (
|
||||
<motion.div key={doc.link} variants={variants.card}>
|
||||
<Link to={doc.link} className="app-card app-card-motion app-card-glow rounded-lg p-5 text-left text-on-surface block group">
|
||||
<div className="mb-2 font-headline text-lg font-bold text-on-surface transition-colors group-hover:text-primary">{doc.title}</div>
|
||||
<div className="text-sm text-on-surface-variant">{doc.description}</div>
|
||||
</Link>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<motion.section
|
||||
id="ecosystem"
|
||||
className="section-surface-alt px-4 py-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.section}>
|
||||
<div className="mx-auto max-w-5xl text-center">
|
||||
<motion.h2 className="mb-10 font-headline text-3xl font-bold text-on-surface" variants={variants.textReveal}>
|
||||
Workflows
|
||||
</motion.h2>
|
||||
<motion.div className="grid grid-cols-1 gap-4 md:grid-cols-2" variants={variants.grid}>
|
||||
{workflowPaths.map((doc) => (
|
||||
<motion.div key={doc.link} variants={variants.card}>
|
||||
<Link to={doc.link} className="app-card app-card-motion app-card-glow rounded-lg p-5 text-left text-on-surface block group">
|
||||
<div className="mb-2 font-headline text-lg font-bold text-on-surface transition-colors group-hover:text-primary">{doc.title}</div>
|
||||
<div className="text-sm text-on-surface-variant">{doc.description}</div>
|
||||
</Link>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<motion.section
|
||||
id="greg-story"
|
||||
className="px-4 py-20"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.section}>
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<motion.div className="app-card app-card-glow rounded-2xl p-6 md:p-8 flex flex-col md:flex-row md:items-center md:justify-between gap-6" variants={variants.card}>
|
||||
<div>
|
||||
<h2 className="mb-4 font-headline text-2xl font-bold text-on-surface md:text-3xl">{t.gregTitle}</h2>
|
||||
<p className="mb-4 text-on-surface-variant text-sm md:text-base leading-relaxed max-w-md">
|
||||
{t.gregText1}
|
||||
</p>
|
||||
<p className="mb-4 text-on-surface-variant text-sm md:text-base leading-relaxed max-w-md">
|
||||
{t.gregText2}
|
||||
</p>
|
||||
<p className="font-headline text-lg font-bold text-secondary italic">{t.gregQuote}</p>
|
||||
</div>
|
||||
<motion.div className="shrink-0" whileHover={reducedMotion ? undefined : { rotate: 1.2, y: -3 }}>
|
||||
<div className="w-32 h-40 md:w-48 md:h-56 overflow-hidden rounded-xl border-2 border-primary/25">
|
||||
<img src={gregImage} alt="Greg" className="h-full w-full object-cover" />
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<motion.section
|
||||
id="community"
|
||||
className="px-4 py-16"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.section}>
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<motion.div
|
||||
className="mb-6 rounded-xl border border-outline-variant/15 bg-surface-container-high p-4"
|
||||
variants={variants.card}>
|
||||
<div className="text-sm font-semibold uppercase tracking-wide text-tertiary">{t.comingSoon}</div>
|
||||
<div className="mt-1 text-base font-medium text-on-surface">{t.comingSoonText}</div>
|
||||
</motion.div>
|
||||
|
||||
<motion.div className="app-card app-card-glow p-6 rounded-xl flex flex-col md:flex-row md:items-center md:justify-between gap-6" variants={variants.card}>
|
||||
<div>
|
||||
<h3 className="font-headline text-2xl font-bold text-on-surface">{t.communityTitle}</h3>
|
||||
<p className="mt-2 text-on-surface-variant">{t.communityText}</p>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<Link to="https://frikadellental.de" className="btn-social">
|
||||
<FaArrowUpRightFromSquare /> frikadellental.de
|
||||
</Link>
|
||||
<Link to="/mods" className="btn-social">
|
||||
<FaShop /> {t.availableModsLabel}
|
||||
</Link>
|
||||
<Link to="https://github.com/mleem97/gregFramework" className="btn-social">
|
||||
<FaGithub /> {t.repositoryLabel}
|
||||
</Link>
|
||||
<Link to="https://discord.gg/greg" className="btn-social bg-[#5865F2] border-transparent text-white hover:bg-[#4752C4]">
|
||||
<FaDiscord /> {t.joinLabel}
|
||||
</Link>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<motion.section
|
||||
id="support"
|
||||
className="section-surface-alt px-4 py-16"
|
||||
initial="hidden"
|
||||
whileInView="show"
|
||||
viewport={viewport}
|
||||
variants={variants.section}>
|
||||
<div className="mx-auto max-w-6xl flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
||||
<div>
|
||||
<h3 className="font-headline text-2xl font-bold text-on-surface">{t.supportTitle}</h3>
|
||||
<p className="text-on-surface-variant">{t.supportText}</p>
|
||||
</div>
|
||||
<motion.div whileHover={reducedMotion ? undefined : { y: -2, scale: 1.01 }}>
|
||||
<Link
|
||||
to="https://github.com/mleem97/gregFramework/issues"
|
||||
className="btn-primary inline-flex items-center gap-2 rounded-xl px-5 py-3">
|
||||
<FaLifeRing /> {t.supportCta}
|
||||
</Link>
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
</main>
|
||||
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
96
src/pages/mods.tsx
Normal file
96
src/pages/mods.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import React, {useMemo} from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import {moduleCatalog} from '../data/moduleCatalog';
|
||||
|
||||
export default function ModsCatalogPage(): JSX.Element {
|
||||
const grouped = useMemo(() => {
|
||||
const plugins = moduleCatalog.filter((entry) => entry.type === 'plugin');
|
||||
const mods = moduleCatalog.filter((entry) => entry.type === 'mod');
|
||||
return {plugins, mods};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout title="Mods Catalog" description="Dynamic catalog of mods and plugins with wiki and release links.">
|
||||
<main className="bg-background min-h-screen text-on-surface px-4 py-12">
|
||||
<section className="mx-auto max-w-6xl mb-10">
|
||||
<h1 className="font-headline text-4xl font-bold text-on-surface mb-3">Mods & Plugins Catalog</h1>
|
||||
<p className="text-on-surface-variant">
|
||||
This page is generated from the module catalog and links each entry to its wiki page, release page, and
|
||||
download route.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mx-auto max-w-6xl mb-10">
|
||||
<h2 className="font-headline text-2xl font-bold text-on-surface mb-4">Plugins</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{grouped.plugins.map((entry) => (
|
||||
<article key={entry.id} className="app-card app-card-motion app-card-glow rounded-xl p-5">
|
||||
<h3 className="font-headline text-lg font-bold text-on-surface mb-2">{entry.name}</h3>
|
||||
<p className="text-sm text-on-surface-variant mb-4">{entry.description}</p>
|
||||
<p className="text-xs text-on-surface-variant mb-1">Version: {entry.version}</p>
|
||||
<p className="text-xs text-on-surface-variant mb-4">Languages: {entry.languages.join(', ')}</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Link to={entry.wikiPath} className="button button--secondary button--sm">
|
||||
Wiki
|
||||
</Link>
|
||||
<Link to={entry.releasePath} className="button button--secondary button--sm">
|
||||
Release
|
||||
</Link>
|
||||
{entry.releaseReady ? (
|
||||
<a href={entry.downloadPath} className="button button--primary button--sm">
|
||||
Download DLL
|
||||
</a>
|
||||
) : (
|
||||
<span
|
||||
className="button button--secondary button--sm cursor-not-allowed opacity-80"
|
||||
role="button"
|
||||
aria-disabled="true"
|
||||
tabIndex={-1}>
|
||||
NotReleasedYet
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mx-auto max-w-6xl">
|
||||
<h2 className="font-headline text-2xl font-bold text-on-surface mb-4">Mods</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{grouped.mods.map((entry) => (
|
||||
<article key={entry.id} className="app-card app-card-motion app-card-glow rounded-xl p-5">
|
||||
<h3 className="font-headline text-lg font-bold text-on-surface mb-2">{entry.name}</h3>
|
||||
<p className="text-sm text-on-surface-variant mb-4">{entry.description}</p>
|
||||
<p className="text-xs text-on-surface-variant mb-1">Version: {entry.version}</p>
|
||||
<p className="text-xs text-on-surface-variant mb-4">Dependencies: {entry.dependencies.join(', ')}</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Link to={entry.wikiPath} className="button button--secondary button--sm">
|
||||
Wiki
|
||||
</Link>
|
||||
<Link to={entry.releasePath} className="button button--secondary button--sm">
|
||||
Release
|
||||
</Link>
|
||||
{entry.releaseReady ? (
|
||||
<a href={entry.downloadPath} className="button button--primary button--sm">
|
||||
Download DLL
|
||||
</a>
|
||||
) : (
|
||||
<span
|
||||
className="button button--secondary button--sm cursor-not-allowed opacity-80"
|
||||
role="button"
|
||||
aria-disabled="true"
|
||||
tabIndex={-1}>
|
||||
NotReleasedYet
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
25
src/pages/wiki.tsx
Normal file
25
src/pages/wiki.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React, {useEffect} from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
export default function WikiLandingPage(): JSX.Element {
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.location.replace('/wiki/docs');
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout title="Wiki" description="Wiki entrypoint">
|
||||
<main className="bg-background min-h-screen text-on-surface px-4 py-16">
|
||||
<section className="mx-auto max-w-3xl text-center app-card app-card-glow glass-card rounded-xl p-8">
|
||||
<h1 className="font-headline text-3xl font-bold text-on-surface mb-3">Wiki</h1>
|
||||
<p className="text-on-surface-variant mb-6">Redirecting to the wiki overview...</p>
|
||||
<Link to="/wiki/docs" className="button button--primary">
|
||||
Open Wiki Overview
|
||||
</Link>
|
||||
</section>
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user