Upgrade Next.js to 15, fix first-load theme bug, add SVG assets

- Upgrade next 14.1.0 → 15.5.9, next-themes 0.2.1 → 0.4.6
- Fix theme not initializing on first load after server restart
- Add SVG logos and favicon, update site-logo to use SVGs
- Create shared Header component with skip-to-main link
- Add portfolio links to bento grid cards
- Improve accessibility: aria-describedby, prefers-reduced-motion
- Fix useFormState → useActionState for React 19 compatibility
- Fix founder-signature icon (use square favicon instead of wide logo)
This commit is contained in:
jwinterm
2026-01-16 21:02:05 -05:00
parent b81bea6297
commit 0d284b5c7d
23 changed files with 1331 additions and 303 deletions
+19 -18
View File
@@ -1,9 +1,7 @@
import { DynamicBackground } from "@/components/landing/dynamic-background";
import { ThemeToggle } from "@/components/theme-toggle";
import { FounderSignature } from "@/components/about/founder-signature";
import { SiteLogo } from "@/components/layout/site-logo";
import Link from "next/link";
import { Header } from "@/components/layout/header";
import { FaMapMarkerAlt, FaPhone, FaBuilding, FaExternalLinkAlt } from "react-icons/fa";
import { FaXTwitter, FaTelegram, FaReddit } from "react-icons/fa6";
import type { Metadata } from "next";
export const metadata: Metadata = {
@@ -19,19 +17,9 @@ export const metadata: Metadata = {
export default function AboutPage() {
return (
<main className="relative flex flex-col items-center overflow-hidden">
<header className="z-50 w-full max-w-7xl mx-auto flex justify-between items-center p-6 bg-background/50 backdrop-blur-3xl sticky top-0 rounded-b-3xl border-b border-border/50">
<div className="flex items-center gap-2">
<SiteLogo />
<nav className="hidden md:flex gap-6 text-sm font-medium">
<Link href="/services" className="hover:text-primary transition-colors">Services</Link>
<Link href="/about" className="text-primary transition-colors">About</Link>
</nav>
</div>
<ThemeToggle />
</header>
<Header />
<div className="z-10 w-full max-w-6xl mx-auto py-20 px-4">
<div id="main-content" className="z-10 w-full max-w-6xl mx-auto py-20 px-4">
<h1 className="text-4xl md:text-5xl font-bold mb-10 text-center">About Us</h1>
<div className="section-container">
@@ -78,8 +66,21 @@ export default function AboutPage() {
<div className="flex flex-col justify-center items-center bg-muted/30 rounded-xl p-6">
<div className="text-center">
<h3 className="text-lg font-semibold mb-2">Connect</h3>
<p className="text-sm text-muted-foreground mb-4">Find us on your favorite platforms</p>
{/* Social links are in the footer, but we can highlight them here or leave for footer */}
<p className="text-sm text-muted-foreground mb-4">Find us on your favorite platforms</p>
<div className="flex gap-6 justify-center">
<a href="https://x.com/such_software" target="_blank" rel="noopener noreferrer" className="text-muted-foreground hover:text-primary transition-colors">
<FaXTwitter className="h-6 w-6" />
<span className="sr-only">X (Twitter)</span>
</a>
<a href="https://t.me/j_winter_m" target="_blank" rel="noopener noreferrer" className="text-muted-foreground hover:text-primary transition-colors">
<FaTelegram className="h-6 w-6" />
<span className="sr-only">Telegram</span>
</a>
<a href="https://reddit.com/r/SuchSoftware" target="_blank" rel="noopener noreferrer" className="text-muted-foreground hover:text-primary transition-colors">
<FaReddit className="h-6 w-6" />
<span className="sr-only">Reddit</span>
</a>
</div>
</div>
</div>
</div>
+14 -2
View File
@@ -87,7 +87,7 @@
overflow: hidden;
transition: all 300ms;
}
.section-container {
@apply mask-backdrop rounded-[2.5rem] p-12 md:p-20 text-card-foreground;
}
@@ -95,8 +95,20 @@
.glass-card {
@apply mask-backdrop rounded-[2rem] p-10 text-card-foreground;
}
.glass-card:hover {
border-color: hsl(var(--primary) / 0.3);
}
}
/* Respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
+2 -1
View File
@@ -12,9 +12,10 @@ export const metadata: Metadata = {
description: "Next-generation web applications engineered for scale, compliance, and performance.",
icons: {
icon: [
{ url: "/images/favicon.svg", type: "image/svg+xml" },
{ url: "/images/favicon_192.png", sizes: "192x192", type: "image/png" },
],
shortcut: "/images/favicon_192.png",
shortcut: "/images/favicon.svg",
apple: [
{ url: "/images/favicon_192.png", sizes: "192x192", type: "image/png" },
],
+4 -17
View File
@@ -1,30 +1,17 @@
import { DynamicBackground } from "@/components/landing/dynamic-background";
import { ThemeToggle } from "@/components/theme-toggle";
import { PortfolioGrid } from "@/components/portfolio/bento-grid";
import { ContactForm } from "@/components/contact/contact-form";
import { FounderSignature } from "@/components/about/founder-signature";
import { ServicesPreview } from "@/components/landing/services-preview";
import { SiteLogo } from "@/components/layout/site-logo";
import { Header } from "@/components/layout/header";
import Link from "next/link";
import { Button } from "@repo/ui/components/button";
import { Card } from "@repo/ui/components/card";
export default function Home() {
return (
<main className="relative flex flex-col items-center justify-between overflow-hidden">
<header className="z-50 w-full max-w-7xl mx-auto flex justify-between items-center p-6 bg-background/50 backdrop-blur-3xl sticky top-0 rounded-b-3xl border-b border-border/50">
<div className="flex items-center gap-2">
<SiteLogo />
<nav className="hidden md:flex gap-6 text-sm font-medium">
<Link href="/services" className="hover:text-primary transition-colors">Services</Link>
<Link href="/about" className="hover:text-primary transition-colors">About</Link>
</nav>
</div>
<ThemeToggle />
</header>
<div className="z-10 w-full max-w-7xl mx-auto flex flex-col items-center pt-20 pb-10 px-4 text-center">
<Header />
<div id="main-content" className="z-10 w-full max-w-7xl mx-auto flex flex-col items-center pt-20 pb-10 px-4 text-center">
<h1 className="text-5xl md:text-7xl font-bold mb-6 bg-clip-text text-transparent bg-gradient-to-r from-blue-500 to-emerald-500 pb-2">
Digital Craftsmanship
</h1>
+5 -18
View File
@@ -1,7 +1,6 @@
import { DataGrid } from "@repo/ui/procedural/data-grid";
import { ThemeToggle } from "@/components/theme-toggle";
import { Button } from "@repo/ui/components/button";
import { SiteLogo } from "@/components/layout/site-logo";
import { Header } from "@/components/layout/header";
import Link from "next/link";
import { Card } from "@repo/ui/components/card";
import type { Metadata } from "next";
@@ -19,22 +18,10 @@ export const metadata: Metadata = {
export default function ServicesPage() {
return (
<main className="relative min-h-screen flex flex-col items-center bg-background text-foreground overflow-hidden">
{/* Option B: Data Grid Background for Technical Feel */}
<DataGrid />
<Header />
<header className="z-50 w-full max-w-7xl mx-auto flex justify-between items-center p-6 bg-background/50 backdrop-blur-3xl sticky top-0 border-b border-border/50 rounded-b-3xl">
<div className="flex items-center gap-2">
<SiteLogo />
<nav className="hidden md:flex gap-6 text-sm font-medium">
<Link href="/services" className="text-primary transition-colors">Services</Link>
<Link href="/about" className="hover:text-primary transition-colors">About</Link>
</nav>
</div>
<ThemeToggle />
</header>
<div className="z-10 w-full max-w-5xl mx-auto py-20 px-4">
<div id="main-content" className="z-10 w-full max-w-5xl mx-auto py-20 px-4">
{/* Context Header */}
<div className="mb-20">
<div className="text-left mb-8 section-container border-l-4 border-l-emerald-500">
@@ -70,8 +57,8 @@ export default function ServicesPage() {
<Card className="glass-card hover:border-indigo-500/30">
<h3 className="text-xl font-bold mb-3">Zero Capital Upfront</h3>
<p className="text-base text-muted-foreground leading-relaxed">
Our "Toast" style partnership means we win when you win. Low friction onboarding
with performance-based incentives.
Our revenue-share partnership means no setup fees or monthly subscriptions—we
only earn when you're making sales.
</p>
</Card>
<Card className="glass-card hover:border-indigo-500/30">