feat: add base styles, component styles, and theme management

- Created base CSS styles for typography, layout, and transitions.
- Added component-specific styles for navigation, hero section, about section, infrastructure, projects, modal, contact, and footer.
- Introduced design tokens for consistent theming across light and dark modes.
- Implemented theme management functionality with local storage support and system preference detection.
- Configured TypeScript settings for the project.
This commit is contained in:
2026-08-11 23:38:08 +08:00
commit 6ea00cfe43
24 changed files with 3528 additions and 0 deletions
+70
View File
@@ -0,0 +1,70 @@
import { infraFallback } from "./data/infra";
const KOMARI_BASE_URL = "https://ops.zhouhaoze.top";
interface KomariNode {
name: string;
region: string; // flag emoji per Komari's public API
}
interface KomariNodesResponse {
data: KomariNode[];
}
export interface RegionBreakdown {
flag: string;
count: number;
}
export interface InfraSnapshot {
serverCount: number;
regionCount: number;
regions: string[];
regionBreakdown: RegionBreakdown[];
live: boolean;
}
export async function fetchInfraSnapshot(): Promise<InfraSnapshot> {
if (!KOMARI_BASE_URL) {
return {
serverCount: infraFallback.serverCount,
regionCount: infraFallback.regionCount,
regions: [],
regionBreakdown: [],
live: false,
};
}
try {
const res = await fetch(`${KOMARI_BASE_URL}/api/nodes`, {
signal: AbortSignal.timeout(5000),
});
if (!res.ok) throw new Error(`Komari responded ${res.status}`);
const body: KomariNodesResponse = await res.json();
const nodes = body.data;
const counts = new Map<string, number>();
for (const n of nodes) {
if (!n.region) continue;
counts.set(n.region, (counts.get(n.region) ?? 0) + 1);
}
const regionBreakdown = Array.from(counts, ([flag, count]) => ({ flag, count }));
const regions = regionBreakdown.map((r) => r.flag);
return {
serverCount: nodes.length || infraFallback.serverCount,
regionCount: regions.length || infraFallback.regionCount,
regions,
regionBreakdown,
live: true,
};
} catch {
return {
serverCount: infraFallback.serverCount,
regionCount: infraFallback.regionCount,
regions: [],
regionBreakdown: [],
live: false,
};
}
}