feat: initial commit — Webflow to Next.js conversion

QuantumLab template converted to Next.js 16 + React 19 + TypeScript:
- 8 page routes (home, about, blog, contact, careers, team-members, coming-soon, 404)
- Dynamic routes for blog posts, career positions, and team members
- GSAP animations (marquee, counters, button hovers)
- IntersectionObserver-based scroll reveal (blur-to-clear transitions)
- Dark mode with next-themes
- React Hook Form + Zod contact form
- Framer Motion page transitions
- Lottie animations via lottie-web

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Leon-in
2026-04-26 18:19:56 +08:00
commit 95eb362bfc
134 changed files with 25831 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env node
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PROJECT_ROOT = path.resolve(__dirname, "..");
const FILES = [
"app/page.tsx",
"app/about/page.tsx",
"app/blog/page.tsx",
"app/contact/page.tsx",
];
for (const file of FILES) {
const filePath = path.join(PROJECT_ROOT, file);
let content = fs.readFileSync(filePath, "utf8");
let hasLottie = false;
// Match any <div ...data-animation-type="lottie"... data-src="..."...>
// Extract className and data-src regardless of attribute order
content = content.replace(
/<div\s[^>]*?data-animation-type="lottie"[^>]*?>/g,
(match) => {
const srcMatch = match.match(/data-src="([^"]*)"/);
const clsMatch = match.match(/className="([^"]*)"/);
if (!srcMatch) return match;
hasLottie = true;
const src = srcMatch[1];
const cls = clsMatch ? clsMatch[1] : "";
return `<LottiePlayer src="${src}" className="${cls}" loop autoplay`;
}
);
// Now close the self-closing LottiePlayer tags
// The original <div> had a matching </div> - we need to remove it
// Pattern: <LottiePlayer ... autoplay\n </div>
content = content.replace(
/(<LottiePlayer[^>]*autoplay)\n(\s*)<\/div>/g,
"$1 />"
);
if (hasLottie) {
if (!content.includes("import LottiePlayer")) {
if (content.startsWith("export")) {
content = `import LottiePlayer from "@/components/LottiePlayer"\n\n${content}`;
}
}
fs.writeFileSync(filePath, content, "utf8");
console.log(`Injected LottiePlayer into ${file}`);
}
}