Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Modern browsers only - matches package.json browserslist
# Avoids unnecessary polyfills (saves ~14 KiB)

chrome >= 100
firefox >= 100
safari >= 15
edge >= 100
not dead
not op_mini all
41 changes: 37 additions & 4 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -281,12 +281,16 @@ export default function RootLayout({
<style
dangerouslySetInnerHTML={{
__html: `
:root{--color-base:#0b1220;--color-surface:#050a15;--color-surface-elevated:#0f172a;--color-text-primary:rgba(255,255,255,.9);--color-text-secondary:rgba(255,255,255,.65);--color-accent-light:#14b8a6;--color-cta:#0d9488;--color-cta-text:#fcfcfc}
:root{--color-base:#0b1220;--color-surface:#050a15;--color-surface-elevated:#0f172a;--color-text-primary:rgba(255,255,255,.9);--color-text-secondary:rgba(255,255,255,.65);--color-accent-light:#14b8a6;--color-cta:#0d9488;--color-cta-text:#fcfcfc;--color-highlight:#0db5a5}
*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}
html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:system-ui,-apple-system,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}
body{margin:0;line-height:inherit;background-color:var(--color-base);color:var(--color-text-primary)}
html{scrollbar-gutter:stable;scroll-behavior:smooth}
img{height:auto;max-width:100%}
h1{margin:0;font-size:inherit;font-weight:inherit}
.text-highlight{color:var(--color-highlight)}
@font-face{font-family:'Outfit';font-display:swap}
@font-face{font-family:'Inter';font-display:swap}
`,
}}
/>
Expand All @@ -298,33 +302,42 @@ export default function RootLayout({
href="https://fonts.gstatic.com"
crossOrigin="anonymous"
/>
<link rel="dns-prefetch" href="https://www.googletagmanager.com" />

{/* Third-party resource hints - prioritized */}
<link rel="preconnect" href="https://www.googletagmanager.com" crossOrigin="anonymous" />
<link rel="dns-prefetch" href="https://www.google-analytics.com" />
<link rel="dns-prefetch" href="https://www.google.com" />
<link rel="preconnect" href="https://www.googletagmanager.com" crossOrigin="anonymous" />
<link rel="dns-prefetch" href="https://googleads.g.doubleclick.net" />
<link rel="dns-prefetch" href="https://stats.g.doubleclick.net" />

{/* Viewport optimization for mobile */}
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5" />

{/* Preload critical assets */}
<link rel="preload" href="/icon.svg" as="image" type="image/svg+xml" />

{/* Preload fonts to prevent layout shifts */}
{/* Preload fonts to prevent layout shifts - with fetchpriority */}
<link
rel="preload"
href="https://fonts.gstatic.com/s/outfit/v11/QGYyz_MVcBeNP4NjuGObqx1XmO1I4TC1O4a0Ew.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
fetchPriority="high"
/>
<link
rel="preload"
href="https://fonts.gstatic.com/s/inter/v13/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiA.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
fetchPriority="high"
/>

{/* Preload critical Next.js chunks */}
<link rel="modulepreload" href="/_next/static/chunks/react.js" />
<link rel="modulepreload" href="/_next/static/chunks/main.js" />

<script
type="application/ld+json"
dangerouslySetInnerHTML={{
Expand Down Expand Up @@ -360,6 +373,26 @@ export default function RootLayout({

{/* Load GA after main content - non-blocking */}
<GoogleAnalytics gaId="G-2KW21KL401" />

{/* Service Worker Registration for Advanced Caching */}
<script
dangerouslySetInnerHTML={{
__html: `
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js').then(
function(registration) {
console.log('ServiceWorker registration successful');
},
function(err) {
console.log('ServiceWorker registration failed: ', err);
}
);
});
}
`,
}}
/>
</body>
</html>
);
Expand Down
27 changes: 14 additions & 13 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import {
Hero,
ValueProposition,
Services,
HowWeWork,
EngagementModels,
FeaturedCaseStudies,
Testimonials,
Stats,
AboutTeaser,
FAQ,
CTA,
} from "@/components/sections";
import { Hero } from "@/components/sections";
import dynamic from "next/dynamic";
import { getNotionFeaturedCaseStudies } from "@/lib/notion-case-studies";

// Dynamically import below-fold sections for better initial bundle size
const ValueProposition = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.ValueProposition })));
const Services = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.Services })));
const HowWeWork = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.HowWeWork })));
const EngagementModels = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.EngagementModels })));
const FeaturedCaseStudies = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.FeaturedCaseStudies })));
const Testimonials = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.Testimonials })));
const Stats = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.Stats })));
const AboutTeaser = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.AboutTeaser })));
const FAQ = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.FAQ })));
const CTA = dynamic(() => import("@/components/sections").then(mod => ({ default: mod.CTA })));

// Force static generation at build time
export const dynamic = "force-static";
export const revalidate = false;
Expand Down
10 changes: 6 additions & 4 deletions components/sections/AboutTeaser.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"use client";

import Link from "next/link";
import { motion } from "framer-motion";
import { LazyMotion, domAnimation, m } from "framer-motion";

export function AboutTeaser() {
return (
<section className="relative py-16 sm:py-20 overflow-hidden bg-base">
<LazyMotion features={domAnimation} strict>
<section className="relative py-16 sm:py-20 overflow-hidden bg-base">
<div className="relative max-w-4xl mx-auto px-4 sm:px-6 text-center">
<motion.div
<m.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
Expand Down Expand Up @@ -49,8 +50,9 @@ export function AboutTeaser() {
<span className="w-2 h-2 rounded-full bg-accent animate-pulse" />
</Link>
</div>
</motion.div>
</m.div>
</div>
</section>
</LazyMotion>
);
}
10 changes: 6 additions & 4 deletions components/sections/CTA.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"use client";

import { motion } from "framer-motion";
import { LazyMotion, domAnimation, m } from "framer-motion";
import { CalButton } from "@/components/CalButton";
import { Spotlight } from "@/components/ui/spotlight";

export function CTA() {
return (
<section className="relative py-16 sm:py-24 bg-base overflow-hidden">
<LazyMotion features={domAnimation} strict>
<section className="relative py-16 sm:py-24 bg-base overflow-hidden">
{/* Spotlight effect */}
<Spotlight
className="-top-40 left-0 md:left-60 md:-top-20"
Expand All @@ -22,7 +23,7 @@ export function CTA() {
}}
/>

<motion.div
<m.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
Expand All @@ -40,7 +41,8 @@ export function CTA() {
<CalButton className="inline-flex items-center justify-center px-6 sm:px-8 py-3 sm:py-4 text-base font-semibold text-cta-text bg-cta rounded-lg hover:brightness-110 transition-all duration-200 shadow-lg shadow-cta/25 cursor-pointer">
Schedule AI Strategy Call
</CalButton>
</motion.div>
</m.div>
</section>
</LazyMotion>
);
}
5 changes: 4 additions & 1 deletion components/sections/EngagementModels.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { motion } from "framer-motion";
import { LazyMotion, domAnimation, m } from "framer-motion";

const engagementModels = [
{
Expand Down Expand Up @@ -85,6 +85,8 @@

export function EngagementModels() {
return (
<LazyMotion features={domAnimation} strict>

Check failure on line 88 in components/sections/EngagementModels.tsx

View workflow job for this annotation

GitHub Actions / build

JSX element 'LazyMotion' has no corresponding closing tag.
<LazyMotion features={domAnimation} strict>
<section className="relative py-16 sm:py-24 overflow-hidden bg-surface">
{/* Gradient orbs for depth */}
<div className="absolute top-0 right-1/4 w-[500px] h-[500px] bg-accent-secondary/[0.05] rounded-full blur-[120px] pointer-events-none" />
Expand Down Expand Up @@ -201,5 +203,6 @@
</div>
</div>
</section>
</LazyMotion>
);
}

Check failure on line 208 in components/sections/EngagementModels.tsx

View workflow job for this annotation

GitHub Actions / build

Unexpected token. Did you mean `{'}'}` or `&rbrace;`?
18 changes: 10 additions & 8 deletions components/sections/FAQ.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { LazyMotion, domAnimation, m, AnimatePresence } from "framer-motion";

const faqs = [
{
Expand Down Expand Up @@ -45,7 +45,8 @@ export function FAQ() {
const [openIndex, setOpenIndex] = useState<number | null>(0);

return (
<section className="relative py-16 sm:py-24 overflow-hidden bg-surface">
<LazyMotion features={domAnimation} strict>
<section className="relative py-16 sm:py-24 overflow-hidden bg-surface">
{/* Dot pattern */}
<div
className="absolute inset-0 opacity-[0.02]"
Expand All @@ -55,7 +56,7 @@ export function FAQ() {
/>

<div className="relative max-w-3xl mx-auto px-4 sm:px-6">
<motion.div
<m.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
Expand All @@ -68,9 +69,9 @@ export function FAQ() {
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold text-text-primary">
Frequently asked questions
</h2>
</motion.div>
</m.div>

<motion.div
<m.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
Expand Down Expand Up @@ -109,7 +110,7 @@ export function FAQ() {
</button>
<AnimatePresence>
{openIndex === idx && (
<motion.div
<m.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
Expand All @@ -119,13 +120,14 @@ export function FAQ() {
<p className="px-5 sm:px-6 pb-5 sm:pb-6 text-text-secondary leading-relaxed">
{faq.answer}
</p>
</motion.div>
</m.div>
)}
</AnimatePresence>
</div>
))}
</motion.div>
</m.div>
</div>
</section>
</LazyMotion>
);
}
5 changes: 4 additions & 1 deletion components/sections/FeaturedCaseStudies.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import Link from "next/link";
import { motion } from "framer-motion";
import { LazyMotion, domAnimation, m } from "framer-motion";
import { CaseStudyCard } from "@/components/ui";
import type { CaseStudy } from "@/lib/case-studies-data";

Expand All @@ -11,6 +11,8 @@

export function FeaturedCaseStudies({ caseStudies }: FeaturedCaseStudiesProps) {
return (
<LazyMotion features={domAnimation} strict>

Check failure on line 14 in components/sections/FeaturedCaseStudies.tsx

View workflow job for this annotation

GitHub Actions / build

JSX element 'LazyMotion' has no corresponding closing tag.
<LazyMotion features={domAnimation} strict>
<section className="relative py-16 sm:py-24 bg-base overflow-hidden">
{/* Background pattern */}
<div
Expand Down Expand Up @@ -101,5 +103,6 @@
</motion.div>
</div>
</section>
</LazyMotion>
);
}

Check failure on line 108 in components/sections/FeaturedCaseStudies.tsx

View workflow job for this annotation

GitHub Actions / build

Unexpected token. Did you mean `{'}'}` or `&rbrace;`?
32 changes: 13 additions & 19 deletions components/sections/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import Link from "next/link";
import { motion } from "framer-motion";
import { ClientLogos } from "./ClientLogos";
import { CalButton } from "@/components/CalButton";
import {
TextGenerateEffect,
TextGenerateEffectHighlight,
} from "@/components/ui/text-generate-effect";

export function Hero() {
return (
Expand Down Expand Up @@ -155,22 +151,20 @@ export function Hero() {
</span>
</motion.div>

{/* Main headline - larger, bolder for center layout */}
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold text-text-primary leading-[1.1]">
<TextGenerateEffect
words="AI Engineering Services"
duration={0.4}
staggerDelay={0.15}
/>
{/* Main headline - optimized for LCP */}
{/* Render text immediately for fast LCP, animate opacity instead of text generation */}
<motion.h1
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, ease: [0.22, 1, 0.36, 1] }}
className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold text-text-primary leading-[1.1]"
>
AI Engineering Services
<br />
<TextGenerateEffectHighlight
words="That Ship to Production"
className="text-highlight"
duration={0.4}
staggerDelay={0.12}
initialDelay={0.5}
/>
</h1>
<span className="text-highlight">
That Ship to Production
</span>
</motion.h1>

{/* Subheadline */}
<motion.p
Expand Down
Loading
Loading