Finalised lab page
This commit is contained in:
parent
ab481053bf
commit
8369d59310
79
app/forge/page.tsx
Normal file
79
app/forge/page.tsx
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
"use client";
|
||||||
|
import { Hammer, History, Target, Code2 } from "lucide-react";
|
||||||
|
import PageLayout from "@/components/PageLayout";
|
||||||
|
|
||||||
|
export default function ForgePage() {
|
||||||
|
return (
|
||||||
|
<PageLayout backLink="/" maxWidth="5xl">
|
||||||
|
<header className="mb-20">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Hammer className="text-orange-500 animate-pulse" size={24} />
|
||||||
|
<h1 className="text-4xl font-bold tracking-tighter text-white uppercase">
|
||||||
|
TheForge
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<p className="text-neutral-500 max-w-2xl leading-relaxed text-sm font-mono">
|
||||||
|
<br />
|
||||||
|
The Forge is where I document my current engineering focus. This space
|
||||||
|
reflects active builds, experimental prototypes and gives a taste of
|
||||||
|
my next releases.
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
{/* Main Project Card */}
|
||||||
|
<section className="bg-neutral-900/40 border border-neutral-800 rounded-2xl p-8 mb-16">
|
||||||
|
<div className="flex flex-wrap items-center justify-between gap-4 mb-8">
|
||||||
|
<div>
|
||||||
|
<h2 className="text-2xl font-bold text-white mb-2 italic">
|
||||||
|
Project: PixelPals
|
||||||
|
</h2>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<span className="text-[10px] text-orange-500 font-bold uppercase tracking-[0.2em]">
|
||||||
|
Build Phase: Alpha 0.1
|
||||||
|
</span>
|
||||||
|
<span className="text-[10px] text-neutral-600 font-bold uppercase tracking-[0.2em]">
|
||||||
|
Engine: Godot / GDScript
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="px-4 py-2 bg-orange-500/10 border border-orange-500/20 rounded-full">
|
||||||
|
<span className="text-[10px] text-orange-500 font-bold uppercase tracking-widest">
|
||||||
|
Active Focus
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-neutral-400 text-sm leading-relaxed mb-8">
|
||||||
|
Exploring procedural generation and state-machine-driven AI behaviors.
|
||||||
|
The goal is to bridge my experience in systems architecture with
|
||||||
|
real-time game loops and interactive storytelling.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Milestones / Changelog */}
|
||||||
|
<div className="space-y-6">
|
||||||
|
<h3 className="flex items-center gap-2 text-xs font-bold text-neutral-500 uppercase tracking-widest border-b border-neutral-800 pb-2">
|
||||||
|
<History size={14} /> Development_Log
|
||||||
|
</h3>
|
||||||
|
<ul className="space-y-4">
|
||||||
|
<li className="flex gap-4">
|
||||||
|
<span className="text-xs text-neutral-600 font-mono mt-1 shrink-0">
|
||||||
|
2026-02-02
|
||||||
|
</span>
|
||||||
|
<p className="text-xs text-neutral-400">
|
||||||
|
Implemented dynamic weather patterns using custom shaders.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li className="flex gap-4">
|
||||||
|
<span className="text-xs text-neutral-600 font-mono mt-1 shrink-0">
|
||||||
|
2026-01-28
|
||||||
|
</span>
|
||||||
|
<p className="text-xs text-neutral-400">
|
||||||
|
Optimized asset loading pipeline for faster initial scene entry.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</PageLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -127,7 +127,7 @@ export default function InfrastructurePage() {
|
||||||
whileTap={{ scale: 0.98 }}
|
whileTap={{ scale: 0.98 }}
|
||||||
className="px-8 py-4 rounded-xl bg-white text-black font-bold text-[11px] uppercase tracking-[0.2em] flex items-center gap-3 transition-all duration-300"
|
className="px-8 py-4 rounded-xl bg-white text-black font-bold text-[11px] uppercase tracking-[0.2em] flex items-center gap-3 transition-all duration-300"
|
||||||
>
|
>
|
||||||
Examine Logic
|
View case
|
||||||
<Zap size={14} />
|
<Zap size={14} />
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { LAB_SERVICES } from "@/data/lab";
|
import { LAB_SERVICES } from "@/data/lab";
|
||||||
import { ExternalLink, Lock, Box, Terminal, Globe } from "lucide-react";
|
import { Lock, Box, Globe } from "lucide-react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import PageLayout from "@/components/PageLayout";
|
import PageLayout from "@/components/PageLayout";
|
||||||
|
|
@ -12,12 +12,12 @@ export default function LabPage() {
|
||||||
<div className="flex items-center gap-2 mb-4">
|
<div className="flex items-center gap-2 mb-4">
|
||||||
<Box className="text-blue-500" size={20} />
|
<Box className="text-blue-500" size={20} />
|
||||||
<h1 className="text-4xl font-bold tracking-tighter text-white uppercase">
|
<h1 className="text-4xl font-bold tracking-tighter text-white uppercase">
|
||||||
System_Lab
|
System Lab
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-neutral-500 max-w-2xl leading-relaxed text-sm">
|
<p className="text-neutral-500 max-w-2xl leading-relaxed text-sm">
|
||||||
A registry of operational services and experimental R&D. Services
|
A registry of self hosted operational services and experimental R&D.
|
||||||
labeled
|
Services labeled
|
||||||
<span className="text-blue-500"> [VPN]</span> are secured via
|
<span className="text-blue-500"> [VPN]</span> are secured via
|
||||||
Tailscale to maintain a hardened perimeter for sensitive telemetry.
|
Tailscale to maintain a hardened perimeter for sensitive telemetry.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
38
app/page.tsx
38
app/page.tsx
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { motion, Variants } from "framer-motion";
|
import { motion, Variants } from "framer-motion";
|
||||||
import { Globe, Smartphone, Server, Gamepad2 } from "lucide-react";
|
import { Globe, Smartphone, Server, Gamepad2, Hammer } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import MonitorCard from "@/components/MonitorCard";
|
import MonitorCard from "@/components/MonitorCard";
|
||||||
import PageLayout from "@/components/PageLayout";
|
import PageLayout from "@/components/PageLayout";
|
||||||
|
|
@ -170,20 +170,28 @@ export default function Home() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Bottom Row: The Forge */}
|
{/* Bottom Row: The Forge */}
|
||||||
<motion.div
|
<Link href="/forge" className="md:col-span-6">
|
||||||
variants={itemVariants}
|
<motion.div
|
||||||
className="md:col-span-6 p-8 rounded-3xl bg-neutral-900/50 border border-neutral-800 flex items-center gap-6 group hover:border-orange-500/30 transition-colors cursor-pointer"
|
variants={itemVariants}
|
||||||
>
|
className="p-8 rounded-3xl bg-neutral-900/50 border border-neutral-800 flex items-center gap-6 group hover:border-orange-500/30 transition-colors cursor-pointer"
|
||||||
<div className="p-4 bg-orange-500/10 rounded-2xl border border-orange-500/20 group-hover:border-orange-500/40 transition-colors">
|
>
|
||||||
<Gamepad2 className="text-orange-500 w-8 h-8" />
|
<div className="p-4 bg-orange-500/10 rounded-2xl border border-orange-500/20 group-hover:border-orange-500/40 transition-colors">
|
||||||
</div>
|
<Hammer className="text-orange-500 w-8 h-8 group-hover:rotate-12 transition-transform" />
|
||||||
<div>
|
</div>
|
||||||
<h3 className="font-bold text-xl">The Forge</h3>
|
<div>
|
||||||
<p className="text-sm text-neutral-500">
|
<div className="flex items-center gap-2 mb-0.5">
|
||||||
Indie Game Dev & Creative Prototypes
|
<h3 className="font-bold text-xl tracking-tight">
|
||||||
</p>
|
The Forge
|
||||||
</div>
|
</h3>
|
||||||
</motion.div>
|
<span className="w-1.5 h-1.5 rounded-full bg-orange-500 animate-pulse" />
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-neutral-500 leading-tight">
|
||||||
|
A space where I demonstrate what I am currently working on and
|
||||||
|
any future projects.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
|
|
|
||||||
26
data/forge.ts
Normal file
26
data/forge.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { ForgeProject } from "@/types";
|
||||||
|
|
||||||
|
export const ACTIVE_BUILD: ForgeProject = {
|
||||||
|
id: "pixelpals",
|
||||||
|
name: "PixelPals",
|
||||||
|
status: "Alpha",
|
||||||
|
engine: "Godot 4.x",
|
||||||
|
description:
|
||||||
|
"A mobile-first creature collection game focusing on procedural behaviors and lightweight state-management.",
|
||||||
|
highlights: [
|
||||||
|
"State-machine AI",
|
||||||
|
"Custom Shader Pipelines",
|
||||||
|
"Mobile-optimized Loops",
|
||||||
|
],
|
||||||
|
externalLink: "/projects/pixelpals", // Link to your internal portfolio or a dedicated site
|
||||||
|
changelog: [
|
||||||
|
{
|
||||||
|
date: "2026-02-03",
|
||||||
|
update: "Refined touch-input latency for mobile devices.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2026-01-25",
|
||||||
|
update: "Integrated local SQLite database for creature persistence.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
22
data/lab.ts
22
data/lab.ts
|
|
@ -9,7 +9,7 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
stack: ["Next.js", "Node", "SQLite"],
|
stack: ["Next.js", "Node", "SQLite"],
|
||||||
visibility: "public",
|
visibility: "public",
|
||||||
url: "https://observatory.georgew.dev",
|
url: "https://observatory.georgew.dev",
|
||||||
gitUrl: "https://git.georgew.dev/george/observatory",
|
gitUrl: "https://git.georgew.dev/georgew/mission-control",
|
||||||
image: "/lab/observatory.jpg",
|
image: "/lab/observatory.jpg",
|
||||||
uptimeId: 12,
|
uptimeId: 12,
|
||||||
},
|
},
|
||||||
|
|
@ -22,6 +22,7 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
visibility: "public",
|
visibility: "public",
|
||||||
url: "https://surf.georgew.dev/d/adrx6b4/llangennith-beach-surf-data?orgId=1&from=now-24h&to=now&timezone=browser&refresh=1h&theme=dark&kiosk=true",
|
url: "https://surf.georgew.dev/d/adrx6b4/llangennith-beach-surf-data?orgId=1&from=now-24h&to=now&timezone=browser&refresh=1h&theme=dark&kiosk=true",
|
||||||
image: "/lab/surf-hub.jpg",
|
image: "/lab/surf-hub.jpg",
|
||||||
|
gitUrl: "https://git.georgew.dev/georgew/surf-hub",
|
||||||
uptimeId: 13,
|
uptimeId: 13,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -31,8 +32,8 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
"Dedicated audiobook server for the household. Primarily used for our Brandon Sanderson, Patrick Rothfuss, and Dungeon Crawler Carl marathons.",
|
"Dedicated audiobook server for the household. Primarily used for our Brandon Sanderson, Patrick Rothfuss, and Dungeon Crawler Carl marathons.",
|
||||||
stack: ["Docker", "Compose", "Tailscale", "rclone"],
|
stack: ["Docker", "Compose", "Tailscale", "rclone"],
|
||||||
visibility: "tailscale",
|
visibility: "tailscale",
|
||||||
url: "https://audio.georgew.dev",
|
|
||||||
image: "/lab/audiobookshelf.jpg",
|
image: "/lab/audiobookshelf.jpg",
|
||||||
|
gitUrl: "https://git.georgew.dev/georgew/audiobookshelf",
|
||||||
uptimeId: 6,
|
uptimeId: 6,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -42,8 +43,8 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
"A specialized tracker for our anime watch-lists! Features custom metadata hooks to keep our seasonal progress in sync.",
|
"A specialized tracker for our anime watch-lists! Features custom metadata hooks to keep our seasonal progress in sync.",
|
||||||
stack: ["Docker", "Redis", "Tailscale"],
|
stack: ["Docker", "Redis", "Tailscale"],
|
||||||
visibility: "tailscale",
|
visibility: "tailscale",
|
||||||
url: "https://anime.georgew.dev",
|
|
||||||
image: "/lab/yamtrack.jpg",
|
image: "/lab/yamtrack.jpg",
|
||||||
|
gitUrl: "https://git.georgew.dev/georgew/yamtrack",
|
||||||
uptimeId: 11,
|
uptimeId: 11,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -53,8 +54,9 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
"Personal document management system with OCR and automated tagging. Digitizing our physical mail and records into a searchable, versioned archive.",
|
"Personal document management system with OCR and automated tagging. Digitizing our physical mail and records into a searchable, versioned archive.",
|
||||||
stack: ["Docker", "Redis", "PostgreSQL"],
|
stack: ["Docker", "Redis", "PostgreSQL"],
|
||||||
visibility: "tailscale",
|
visibility: "tailscale",
|
||||||
url: "https://paperless.georgew.dev",
|
|
||||||
image: "/lab/paperless.jpg",
|
image: "/lab/paperless.jpg",
|
||||||
|
gitUrl: "https://git.georgew.dev/georgew/paperless-ngx",
|
||||||
|
|
||||||
uptimeId: 14,
|
uptimeId: 14,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -64,8 +66,8 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
"Automated monitoring for the essentials: NASA news updates, hobby stock alerts, and Telegram pings the second a new episode of 'The Traitors' drops.",
|
"Automated monitoring for the essentials: NASA news updates, hobby stock alerts, and Telegram pings the second a new episode of 'The Traitors' drops.",
|
||||||
stack: ["Telegram API", "Webhooks"],
|
stack: ["Telegram API", "Webhooks"],
|
||||||
visibility: "tailscale",
|
visibility: "tailscale",
|
||||||
url: "https://alerts.georgew.dev",
|
|
||||||
image: "/lab/change-detection.jpg",
|
image: "/lab/change-detection.jpg",
|
||||||
|
gitUrl: "https://git.georgew.dev/georgew/change-detection",
|
||||||
uptimeId: 15,
|
uptimeId: 15,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -75,7 +77,6 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
"The 'Engine Room.' Utilizing Portainer for orchestration, Dozzle for log streaming, and Watchtower for automated container lifecycle management across the Hetzner node.",
|
"The 'Engine Room.' Utilizing Portainer for orchestration, Dozzle for log streaming, and Watchtower for automated container lifecycle management across the Hetzner node.",
|
||||||
stack: ["Portainer", "Dozzle", "Watchtower"],
|
stack: ["Portainer", "Dozzle", "Watchtower"],
|
||||||
visibility: "tailscale",
|
visibility: "tailscale",
|
||||||
url: "https://portainer.georgew.dev",
|
|
||||||
image: "/lab/portainer.jpg",
|
image: "/lab/portainer.jpg",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -85,7 +86,6 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
"The 'Source of Truth' for the home infrastructure. Contains deployment guides, network maps, and disaster recovery procedures for the entire node.",
|
"The 'Source of Truth' for the home infrastructure. Contains deployment guides, network maps, and disaster recovery procedures for the entire node.",
|
||||||
stack: ["Wiki.js", "Markdown"],
|
stack: ["Wiki.js", "Markdown"],
|
||||||
visibility: "tailscale",
|
visibility: "tailscale",
|
||||||
url: "https://wiki.georgew.dev",
|
|
||||||
image: "/lab/wikijs.jpg",
|
image: "/lab/wikijs.jpg",
|
||||||
uptimeId: 5,
|
uptimeId: 5,
|
||||||
},
|
},
|
||||||
|
|
@ -93,11 +93,9 @@ export const LAB_SERVICES: LabService[] = [
|
||||||
id: "dashboard",
|
id: "dashboard",
|
||||||
name: "System Dashboard",
|
name: "System Dashboard",
|
||||||
description:
|
description:
|
||||||
"The central entry point for the GeorgeW ecosystem. A high-level overview providing unified access to all public and VPN-secured services.",
|
"The central entry point for the GeorgeW ecosystem, used as my personal home page. A high-level overview providing unified access to all public and VPN-secured services.",
|
||||||
stack: ["Next.js", "Docker", "Reverse Proxy"],
|
stack: ["Homepage", "Docker", "Reverse Proxy"],
|
||||||
visibility: "public",
|
visibility: "tailscale",
|
||||||
url: "https://dash.georgew.dev",
|
|
||||||
gitUrl: "https://git.georgew.dev/george/homepage",
|
|
||||||
image: "/lab/dashboard.jpg",
|
image: "/lab/dashboard.jpg",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
BIN
public/lab/dashboard.jpg
Normal file
BIN
public/lab/dashboard.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 250 KiB |
|
|
@ -47,3 +47,14 @@ export interface LabService {
|
||||||
image: string;
|
image: string;
|
||||||
uptimeId?: number;
|
uptimeId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ForgeProject {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
status: "Alpha" | "Beta" | "R&D";
|
||||||
|
engine: string;
|
||||||
|
description: string;
|
||||||
|
highlights: string[];
|
||||||
|
externalLink?: string;
|
||||||
|
changelog: { date: string; update: string }[];
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue