From ab97718607ec063e58331e425276a5798cfcfd0a Mon Sep 17 00:00:00 2001 From: Jerry Xiao Date: Wed, 6 May 2026 12:59:29 -0700 Subject: [PATCH] migrate to Next.js + TypeScript + React MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full migration from static HTML/CSS/JS to Next.js 15 App Router: - 4 routes (/, /recon, /pulse, /helm) as server components, prerendered statically - Shared Nav, Footer, Marquee, Terminal, RadarMark components - main.js ported to GsapClient (use client) — useEffect keyed to pathname so animations re-init across soft navigations, and ScrollTriggers are torn down on route change - styles.css → app/globals.css; body[data-theme] selectors switched to [data-theme] so each page wraps content in a themed div - rm-progress gradient now uses --accent + --accent-glow vars so it picks up the helm-blue theme without a separate override - Static assets moved to public/ - Old HTML/CSS/JS files removed - vercel.json removed — Next.js framework detection handles routing and clean URLs natively Build output: 153 kB first-load JS shared, ~2.7 kB per route. Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 4 + styles.css => app/globals.css | 19 +- app/helm/page.tsx | 404 +++++++++++ app/layout.tsx | 41 ++ app/page.tsx | 481 ++++++++++++++ app/pulse/page.tsx | 399 +++++++++++ app/recon/page.tsx | 784 ++++++++++++++++++++++ components/Footer.tsx | 51 ++ components/GsapClient.tsx | 427 ++++++++++++ components/Marquee.tsx | 20 + components/Nav.tsx | 114 ++++ components/RadarMark.tsx | 23 + components/Terminal.tsx | 40 ++ helm.html | 343 ---------- index.html | 376 ----------- main.js | 482 -------------- next-env.d.ts | 6 + next.config.mjs | 17 + package-lock.json | 1030 +++++++++++++++++++++++++++++ package.json | 23 + favicon.svg => public/favicon.svg | 0 robots.txt => public/robots.txt | 0 sitemap.xml => public/sitemap.xml | 0 pulse.html | 338 ---------- recon.html | 620 ----------------- tsconfig.json | 21 + vercel.json | 18 - 27 files changed, 3890 insertions(+), 2191 deletions(-) rename styles.css => app/globals.css (98%) create mode 100644 app/helm/page.tsx create mode 100644 app/layout.tsx create mode 100644 app/page.tsx create mode 100644 app/pulse/page.tsx create mode 100644 app/recon/page.tsx create mode 100644 components/Footer.tsx create mode 100644 components/GsapClient.tsx create mode 100644 components/Marquee.tsx create mode 100644 components/Nav.tsx create mode 100644 components/RadarMark.tsx create mode 100644 components/Terminal.tsx delete mode 100644 helm.html delete mode 100644 index.html delete mode 100644 main.js create mode 100644 next-env.d.ts create mode 100644 next.config.mjs create mode 100644 package-lock.json create mode 100644 package.json rename favicon.svg => public/favicon.svg (100%) rename robots.txt => public/robots.txt (100%) rename sitemap.xml => public/sitemap.xml (100%) delete mode 100644 pulse.html delete mode 100644 recon.html create mode 100644 tsconfig.json delete mode 100644 vercel.json diff --git a/.gitignore b/.gitignore index f773e52..848b0dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ .DS_Store .vercel node_modules +.next +out +*.tsbuildinfo +.env*.local diff --git a/styles.css b/app/globals.css similarity index 98% rename from styles.css rename to app/globals.css index 14175c8..54df9c9 100644 --- a/styles.css +++ b/app/globals.css @@ -54,12 +54,12 @@ body::before { z-index: 0; } /* theme variants — applied via body[data-theme] */ -body[data-theme="helm"] { +[data-theme="helm"] { --accent: #7ec5ff; --accent-soft: rgba(126, 197, 255, 0.12); --accent-glow: rgba(126, 197, 255, 0.35); } -body[data-theme="agency"] { +[data-theme="agency"] { --accent: #7892bd; --accent-soft: rgba(120, 146, 189, 0.13); --accent-glow: rgba(120, 146, 189, 0.38); @@ -117,12 +117,12 @@ body.ready .spotlight { opacity: 1; } } /* Denim brand mark for 42nights — used on /, and as the parent-brand mark on pulse/helm navs */ .brand-mark.denim, -body[data-theme="agency"] .brand-mark { +[data-theme="agency"] .brand-mark { background: linear-gradient(135deg, #88a3cd 0%, #5a7bb0 100%); color: #f5f7fb; box-shadow: 0 0 0 1px rgba(120, 146, 189, 0.35), 0 0 24px -2px rgba(120, 146, 189, 0.45); } -body[data-theme="helm"] .brand-mark:not(.denim) { +[data-theme="helm"] .brand-mark:not(.denim) { background: linear-gradient(135deg, #b6dcff 0%, #5a9adc 100%); color: #07101c; box-shadow: 0 0 0 1px rgba(126, 197, 255, 0.32), 0 0 24px -2px rgba(126, 197, 255, 0.45); @@ -310,11 +310,6 @@ body[data-theme="helm"] .brand-mark:not(.denim) { box-shadow: 0 0 0 1px rgba(205, 251, 83, 0.5), 0 6px 20px -4px var(--accent-glow); transition: background 320ms var(--ease-out), box-shadow 320ms var(--ease-out); } -body[data-phase="pe"] .pt-indicator { - background: var(--helm); - box-shadow: 0 0 0 1px rgba(126, 197, 255, 0.5), 0 6px 20px -4px rgba(126, 197, 255, 0.35); -} - /* hero-stage holds both phases stacked */ .hero-stage { position: relative; @@ -837,14 +832,10 @@ body[data-phase="pe"] .pt-indicator { position: absolute; left: 16px; top: 50%; width: 0; height: 1px; - background: linear-gradient(90deg, var(--accent), rgba(205,251,83,0.7)); + background: linear-gradient(90deg, var(--accent), var(--accent-glow)); box-shadow: 0 0 10px var(--accent-glow); transform: translateY(-50%); } -body[data-phase="pe"] .rm-progress { - background: linear-gradient(90deg, var(--helm), rgba(126,197,255,0.7)); - box-shadow: 0 0 10px rgba(126,197,255,0.4); -} .rm-dot { position: relative; z-index: 2; width: 32px; height: 32px; diff --git a/app/helm/page.tsx b/app/helm/page.tsx new file mode 100644 index 0000000..a22e99a --- /dev/null +++ b/app/helm/page.tsx @@ -0,0 +1,404 @@ +import type { Metadata } from 'next'; +import Link from 'next/link'; +import GsapClient from '@/components/GsapClient'; +import Nav from '@/components/Nav'; +import Footer from '@/components/Footer'; +import Marquee from '@/components/Marquee'; +import Terminal from '@/components/Terminal'; + +export const metadata: Metadata = { + title: 'Helm — the portfolio operating cockpit', + description: + 'KPI roll-ups across portcos, variance flags, board-pack agent. On infrastructure you control. Built on Recon, deployed by 42nights.', + alternates: { canonical: '/helm' }, + openGraph: { + type: 'website', + url: '/helm', + title: 'Helm — portfolio cockpit on your infra', + description: + 'KPI roll-ups, variance flags, DD workspace, board-pack agent. Built on Recon, deployed by 42nights.', + siteName: '42nights', + }, + twitter: { + card: 'summary_large_image', + title: 'Helm — portfolio cockpit on your infra', + description: + 'KPI roll-ups, variance flags, DD workspace, board-pack agent. Built on Recon, deployed by 42nights.', + }, +}; + +export const viewport = { themeColor: '#7ec5ff' }; + +const ArrowSm = () => ( + + + +); + +export default function HelmPage() { + return ( +
+