diff --git a/apps/web/package.json b/apps/web/package.json index 6d0c9ee..6dc0632 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,8 +14,8 @@ "@repo/ui": "workspace:*", "framer-motion": "^11.0.0", "lucide-react": "^0.350.0", - "next": "14.1.0", - "next-themes": "^0.2.1", + "next": "^15.1.3", + "next-themes": "^0.4.6", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^5.5.0", @@ -27,7 +27,7 @@ "@types/react-dom": "^18.0.0", "autoprefixer": "^10.0.1", "eslint": "^8", - "eslint-config-next": "14.1.0", + "eslint-config-next": "^15.1.3", "postcss": "^8", "tailwindcss": "^3.3.0", "tailwindcss-animate": "^1.0.7", diff --git a/apps/web/public/images/favicon.svg b/apps/web/public/images/favicon.svg new file mode 100644 index 0000000..9a7d282 --- /dev/null +++ b/apps/web/public/images/favicon.svg @@ -0,0 +1,119 @@ + + + + diff --git a/apps/web/public/images/logo_dark.svg b/apps/web/public/images/logo_dark.svg new file mode 100644 index 0000000..b1da386 --- /dev/null +++ b/apps/web/public/images/logo_dark.svg @@ -0,0 +1,55 @@ + + + + diff --git a/apps/web/public/images/logo_dark_w_name.svg b/apps/web/public/images/logo_dark_w_name.svg new file mode 100644 index 0000000..fee8962 --- /dev/null +++ b/apps/web/public/images/logo_dark_w_name.svg @@ -0,0 +1,119 @@ + + + +SuchSoftware diff --git a/apps/web/public/images/logo_light.svg b/apps/web/public/images/logo_light.svg new file mode 100644 index 0000000..774245f --- /dev/null +++ b/apps/web/public/images/logo_light.svg @@ -0,0 +1,55 @@ + + + + diff --git a/apps/web/public/images/logo_light_w_name.svg b/apps/web/public/images/logo_light_w_name.svg new file mode 100644 index 0000000..220d011 --- /dev/null +++ b/apps/web/public/images/logo_light_w_name.svg @@ -0,0 +1,119 @@ + + + +SuchSoftware diff --git a/apps/web/public/manifest.json b/apps/web/public/manifest.json index 533ead2..61faa2a 100644 --- a/apps/web/public/manifest.json +++ b/apps/web/public/manifest.json @@ -7,6 +7,11 @@ "background_color": "#000000", "theme_color": "#000000", "icons": [ + { + "src": "/images/favicon.svg", + "type": "image/svg+xml", + "purpose": "any" + }, { "src": "/images/favicon_192.png", "sizes": "192x192", diff --git a/apps/web/src/app/about/page.tsx b/apps/web/src/app/about/page.tsx index dadd7a0..34771b7 100644 --- a/apps/web/src/app/about/page.tsx +++ b/apps/web/src/app/about/page.tsx @@ -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 (
- -
-
- - -
- -
+
-
+

About Us

@@ -78,8 +66,21 @@ export default function AboutPage() {

Connect

-

Find us on your favorite platforms

- {/* Social links are in the footer, but we can highlight them here or leave for footer */} +

Find us on your favorite platforms

+
diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index 8bcd3b7..da800a2 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -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; + } +} diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index 292cf4b..cef57d0 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -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" }, ], diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index fa1f847..5068f86 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -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 (
- -
-
- - -
- -
- -
+
+ +

Digital Craftsmanship

diff --git a/apps/web/src/app/services/page.tsx b/apps/web/src/app/services/page.tsx index 26eaa07..c35dfea 100644 --- a/apps/web/src/app/services/page.tsx +++ b/apps/web/src/app/services/page.tsx @@ -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 (
- - {/* Option B: Data Grid Background for Technical Feel */} +
-
-
- - -
- -
- -
+
{/* Context Header */}
@@ -70,8 +57,8 @@ export default function ServicesPage() {

Zero Capital Upfront

- 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.

diff --git a/apps/web/src/components/about/founder-signature.tsx b/apps/web/src/components/about/founder-signature.tsx index 55764a1..e7f685d 100644 --- a/apps/web/src/components/about/founder-signature.tsx +++ b/apps/web/src/components/about/founder-signature.tsx @@ -7,12 +7,13 @@ export const FounderSignature = () => { {/* Left Column: Bio */}
-
- Such Software Icon + Such Software Icon
@@ -23,13 +24,13 @@ export const FounderSignature = () => {

- "During my three years at Cecil College, I didn't just teach web engineering—I re-engineered how it was taught. + "During my three years at Cecil College, I didn't just teach engineering—I re-engineered how it was taught.

- Transitioning the curriculum toward from PDFs and Powerpoints to web-based content, I focused on transforming complex technical lessons into highly accessible HTML using Quarto markdown as our source. This allowed us to consistently generate semantic content including accessible equations and guaranteed descriptive alt text for every visual asset. + Transitioning the curriculum from PDFs and Powerpoints to web-based content, I focused on transforming complex technical lessons into highly accessible HTML using Quarto markdown. This allowed us to consistently generate semantic content including accessible equations and guaranteed descriptive alt text for every visual asset.

- This wasn't just academic theory; it was a rigorous discipline of semantic architecture, ARIA compliance, and cognitive load management. Today, I bring that same technical rigor to Such Software’s commercial projects. We don't retroactively fix accessibility; we architect for it from line one." + This wasn't just theory; it was a methodical implementation of semantic architecture, ARIA compliance, and cognitive load management. Today, I bring that same technical rigor to Such Software’s commercial projects. We don't retroactively fix accessibility; we architect for it from line one."

@@ -61,18 +62,18 @@ export const FounderSignature = () => { 03 Core Competencies -
    +
    • - ✓ WCAG 2.2 AA Compliance + ✓ WCAG 2.2 AA Compliance
    • - ✓ Section 508 & ADA + ✓ Section 508 & ADA
    • - ✓ Semantic HTML5 Architecture + ✓ Semantic HTML5 Architecture
    • - ✓ Playwright A11y Automation + ✓ Playwright A11y Automation
    diff --git a/apps/web/src/components/contact/contact-form.tsx b/apps/web/src/components/contact/contact-form.tsx index 4799434..46a3173 100644 --- a/apps/web/src/components/contact/contact-form.tsx +++ b/apps/web/src/components/contact/contact-form.tsx @@ -1,16 +1,17 @@ 'use client'; -import { useFormState, useFormStatus } from 'react-dom'; +import { useActionState } from 'react'; +import { useFormStatus } from 'react-dom'; import { submitContactForm } from '@/actions/submit-contact'; import { TurnstileWidget } from './turnstile-widget'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { Button } from '@repo/ui/components/button'; function SubmitButton() { const { pending } = useFormStatus(); return ( -