From a3b1a3bfdf8714469e35d431f28d559619326c73 Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Fri, 7 Nov 2025 23:02:37 -0800 Subject: add instance info to landing page --- README.md | 3 +- backend/.env.example | 1 + frontend/src/pages/Landing.tsx | 78 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bd180b1..310b324 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Mirage -**Mirage** is a "rhythm" game score tracker that doesn’t rely on predefined seeds or chart metadata. It preseves your scores across games — even niche ones. +**Mirage** is a self-hostable "rhythm" game score tracker that doesn’t rely on predefined seeds or chart metadata. It preseves your scores across games, even niche ones. ![https://github.com/user-attachments/assets/e1a03b39-3c6f-4d31-8a4e-7ae9abaa93a2](https://github.com/user-attachments/assets/e1a03b39-3c6f-4d31-8a4e-7ae9abaa93a2) ![https://github.com/user-attachments/assets/63341f3b-991c-4147-8014-30f27020dc05](https://github.com/user-attachments/assets/63341f3b-991c-4147-8014-30f27020dc05) @@ -18,6 +18,7 @@ - MUSIC DIVER - Nostalgia - REFLEC BEAT +- Taiko no Tatsujin Arcade > [!NOTE] > Basically stuff that isn't supported by [Tachi](https://github.com/zkrising/Tachi) (*yet?*), you should use it for all the other games it does support diff --git a/backend/.env.example b/backend/.env.example index f570912..e6356a9 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -2,3 +2,4 @@ DATABASE_URL="postgresql://postgres@localhost:5432/mirage" SESSION_SECRET="your-very-secure-secret-key-change-this-in-production-make-it-long-and-random" PORT=5000 NODE_ENV=development +REQUIRE_INVITE=true # needs an invite to join diff --git a/frontend/src/pages/Landing.tsx b/frontend/src/pages/Landing.tsx index e3b7898..20eb887 100644 --- a/frontend/src/pages/Landing.tsx +++ b/frontend/src/pages/Landing.tsx @@ -1,7 +1,38 @@ import { Link } from "react-router"; +import { useEffect, useState } from "react"; +import type { SupportedGame } from "../types/game"; import sakuraMirageImage from "../assets/games/mirage.webp"; const Landing = () => { + const [requireInvite, setRequireInvite] = useState(false); + const [numUsers, setNumUsers] = useState(0); + const [supportedGames, setSupportedGames] = useState(null); + useEffect(() => { + const fetchServerInfo = async () => { + try { + const response = await fetch(import.meta.env.VITE_API_URL + "/info"); + const data = await response.json(); + setRequireInvite(Boolean(data.requireInvite)); + setNumUsers(Number(data.userCount)); + } catch (error) { + console.error('Error fetching server info:', error); + } + }; + + const fetchSupportedGames = async () => { + try { + const response = await fetch(import.meta.env.VITE_API_URL + "/supportedGames"); + const data = await response.json(); + setSupportedGames(data); + } catch (error) { + console.error('Error fetching supported games:', error); + } + }; + fetchServerInfo(); + fetchSupportedGames(); + }, []); + + return (
{/* Navigation */} @@ -64,6 +95,53 @@ const Landing = () => {
+ {/* Server Stats Section */} +
+
+
+

+ Server Status +

+
+
+

Users

+

{numUsers}

+

registered users

+
+
+

Registration

+

+ {requireInvite ? "Invite Only" : "Open"} +

+

+ {requireInvite ? "ask an admin" : "anyone can join"} +

+
+
+

Games

+

+ {supportedGames ? supportedGames.length : "Loading..."} +

+

supported games

+
+
+ {supportedGames && supportedGames.length > 0 && ( +
+

Supported Games

+
+ {supportedGames.map((game) => ( +
+

{game.formattedName}

+

{game.description}

+
+ ))} +
+
+ )} +
+
+
+ {/* Introduction Section */}
-- cgit v1.2.3