diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 942b8a5..4024db2 100755
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -22,10 +22,12 @@
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@tanstack/react-query": "^5.90.5",
+ "@types/react-syntax-highlighter": "^15.5.13",
"axios": "^1.13.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
+ "framer-motion": "^12.23.24",
"gray-matter": "^4.0.3",
"lucide-react": "^0.552.0",
"next": "^15.5.6",
@@ -34,6 +36,7 @@
"react-dom": "^19.0.0",
"react-hook-form": "^7.66.0",
"react-markdown": "^10.1.0",
+ "react-syntax-highlighter": "^16.1.0",
"recharts": "^2.15.4",
"rehype-autolink-headings": "^7.1.0",
"rehype-highlight": "^7.0.2",
@@ -5185,6 +5188,12 @@
"@types/pg": "*"
}
},
+ "node_modules/@types/prismjs": {
+ "version": "1.26.5",
+ "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.5.tgz",
+ "integrity": "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==",
+ "license": "MIT"
+ },
"node_modules/@types/react": {
"version": "19.2.2",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
@@ -5204,6 +5213,15 @@
"@types/react": "^19.2.0"
}
},
+ "node_modules/@types/react-syntax-highlighter": {
+ "version": "15.5.13",
+ "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz",
+ "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/shimmer": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz",
@@ -8757,6 +8775,19 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/fault": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz",
+ "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==",
+ "license": "MIT",
+ "dependencies": {
+ "format": "^0.2.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/fb-watchman": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
@@ -8910,6 +8941,14 @@
"node": ">= 6"
}
},
+ "node_modules/format": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
+ "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
"node_modules/forwarded-parse": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz",
@@ -8917,6 +8956,33 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/framer-motion": {
+ "version": "12.23.24",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz",
+ "integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-dom": "^12.23.23",
+ "motion-utils": "^12.23.6",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -9456,6 +9522,19 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/hast-util-parse-selector": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz",
+ "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/hast-util-to-jsx-runtime": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
@@ -9525,6 +9604,23 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/hastscript": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz",
+ "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-parse-selector": "^4.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/highlight.js": {
"version": "11.11.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
@@ -9534,6 +9630,12 @@
"node": ">=12.0.0"
}
},
+ "node_modules/highlightjs-vue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz",
+ "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==",
+ "license": "CC0-1.0"
+ },
"node_modules/html-encoding-sniffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
@@ -13199,6 +13301,21 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/motion-dom": {
+ "version": "12.23.23",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz",
+ "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-utils": "^12.23.6"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.23.6",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
+ "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==",
+ "license": "MIT"
+ },
"node_modules/mrmime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
@@ -14216,6 +14333,15 @@
"license": "MIT",
"peer": true
},
+ "node_modules/prismjs": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -14553,6 +14679,49 @@
}
}
},
+ "node_modules/react-syntax-highlighter": {
+ "version": "16.1.0",
+ "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-16.1.0.tgz",
+ "integrity": "sha512-E40/hBiP5rCNwkeBN1vRP+xow1X0pndinO+z3h7HLsHyjztbyjfzNWNKuAsJj+7DLam9iT4AaaOZnueCU+Nplg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.28.4",
+ "highlight.js": "^10.4.1",
+ "highlightjs-vue": "^1.0.0",
+ "lowlight": "^1.17.0",
+ "prismjs": "^1.30.0",
+ "refractor": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 16.20.2"
+ },
+ "peerDependencies": {
+ "react": ">= 0.14.0"
+ }
+ },
+ "node_modules/react-syntax-highlighter/node_modules/highlight.js": {
+ "version": "10.7.3",
+ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
+ "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/react-syntax-highlighter/node_modules/lowlight": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz",
+ "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==",
+ "license": "MIT",
+ "dependencies": {
+ "fault": "^1.0.0",
+ "highlight.js": "~10.7.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -14658,6 +14827,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/refractor": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/refractor/-/refractor-5.0.0.tgz",
+ "integrity": "sha512-QXOrHQF5jOpjjLfiNk5GFnWhRXvxjUVnlFxkeDmewR5sXkr3iM46Zo+CnRR8B+MDVqkULW4EcLVcRBNOPXHosw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/prismjs": "^1.0.0",
+ "hastscript": "^9.0.0",
+ "parse-entities": "^4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/regexp.prototype.flags": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index fdfd66d..054b6bf 100755
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -35,10 +35,12 @@
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@tanstack/react-query": "^5.90.5",
+ "@types/react-syntax-highlighter": "^15.5.13",
"axios": "^1.13.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
+ "framer-motion": "^12.23.24",
"gray-matter": "^4.0.3",
"lucide-react": "^0.552.0",
"next": "^15.5.6",
@@ -47,6 +49,7 @@
"react-dom": "^19.0.0",
"react-hook-form": "^7.66.0",
"react-markdown": "^10.1.0",
+ "react-syntax-highlighter": "^16.1.0",
"recharts": "^2.15.4",
"rehype-autolink-headings": "^7.1.0",
"rehype-highlight": "^7.0.2",
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index 3eee014..2911460 100755
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -1,100 +1,95 @@
-import Image from "next/image";
+/**
+ * Homepage / Landing Page
+ * Main landing page for the FastNext Template project
+ * Showcases features, tech stack, and provides demos for developers
+ */
+
+import { Header } from '@/components/home/Header';
+import { HeroSection } from '@/components/home/HeroSection';
+import { ContextSection } from '@/components/home/ContextSection';
+import { AnimatedTerminal } from '@/components/home/AnimatedTerminal';
+import { FeatureGrid } from '@/components/home/FeatureGrid';
+import { DemoSection } from '@/components/home/DemoSection';
+import { StatsSection } from '@/components/home/StatsSection';
+import { TechStackSection } from '@/components/home/TechStackSection';
+import { PhilosophySection } from '@/components/home/PhilosophySection';
+import { QuickStartCode } from '@/components/home/QuickStartCode';
+import { CTASection } from '@/components/home/CTASection';
export default function Home() {
return (
-
-
-
-
-
- Get started by editing{" "}
-
- src/app/page.tsx
-
- .
-
- Save and see your changes instantly.
-
+
+ {/* Header Navigation */}
+
-
+ {/* Main Content */}
+
+ {/* Hero Section with CTAs */}
+
+
+ {/* What is this template? */}
+
+
+ {/* Animated Terminal with Quick Start */}
+
+
+ {/* 6 Feature Cards Grid */}
+
+
+ {/* Interactive Demo Cards */}
+
+
+ {/* Statistics with Animated Counters */}
+
+
+ {/* Tech Stack Grid */}
+
+
+ {/* For Developers, By Developers */}
+
+
+ {/* Quick Start Code Block */}
+
+
+ {/* Final CTA Section */}
+
-
);
diff --git a/frontend/src/components/home/AnimatedTerminal.tsx b/frontend/src/components/home/AnimatedTerminal.tsx
new file mode 100644
index 0000000..7c0ae12
--- /dev/null
+++ b/frontend/src/components/home/AnimatedTerminal.tsx
@@ -0,0 +1,140 @@
+/**
+ * Animated Terminal
+ * Terminal with typing animation showing installation/setup commands
+ */
+
+'use client';
+
+import { useEffect, useState, useRef } from 'react';
+import { motion } from 'framer-motion';
+import { Terminal, Play } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import Link from 'next/link';
+
+const commands = [
+ { text: '# Clone the repository', delay: 0 },
+ { text: '$ git clone https://github.com/your-org/fast-next-template.git', delay: 800 },
+ { text: '$ cd fast-next-template', delay: 1600 },
+ { text: '', delay: 2200 },
+ { text: '# Start with Docker (one command)', delay: 2400 },
+ { text: '$ docker-compose up', delay: 3200 },
+ { text: '', delay: 4000 },
+ { text: '✓ Backend running at http://localhost:8000', delay: 4200, isSuccess: true },
+ { text: '✓ Frontend running at http://localhost:3000', delay: 4400, isSuccess: true },
+ { text: '✓ Admin panel at http://localhost:3000/admin', delay: 4600, isSuccess: true },
+ { text: '✓ API docs at http://localhost:8000/docs', delay: 4800, isSuccess: true },
+];
+
+export function AnimatedTerminal() {
+ const [displayedLines, setDisplayedLines] = useState([]);
+ const [isAnimating, setIsAnimating] = useState(false);
+ const containerRef = useRef(null);
+ const hasAnimated = useRef(false);
+
+ useEffect(() => {
+ // Only animate once when component enters viewport
+ if (hasAnimated.current) return;
+
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ if (entry.isIntersecting && !hasAnimated.current) {
+ hasAnimated.current = true;
+ setIsAnimating(true);
+ animateCommands();
+ }
+ },
+ { threshold: 0.3 }
+ );
+
+ if (containerRef.current) {
+ observer.observe(containerRef.current);
+ }
+
+ return () => observer.disconnect();
+ }, []);
+
+ const animateCommands = () => {
+ commands.forEach((cmd) => {
+ setTimeout(() => {
+ setDisplayedLines((prev) => [...prev, cmd]);
+ }, cmd.delay);
+ });
+ };
+
+ return (
+
+
+ {/* Title */}
+
+
Get Started in Seconds
+
+ Clone, run, and start building. No complex setup required.
+
+
+
+ {/* Terminal Window */}
+
+ {/* Terminal Header */}
+
+
+ {/* Terminal Content */}
+
+
+ {displayedLines.map((line, index) => (
+
+ {line.text || '\u00A0'}
+ {index === displayedLines.length - 1 && isAnimating && !line.isSuccess && (
+
+ )}
+
+ ))}
+
+
+
+
+ {/* CTA Below Terminal */}
+
+
+ Or try the live demo without installing anything
+
+
+
+
+ Try Live Demo
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/home/CTASection.tsx b/frontend/src/components/home/CTASection.tsx
new file mode 100644
index 0000000..8f7bf53
--- /dev/null
+++ b/frontend/src/components/home/CTASection.tsx
@@ -0,0 +1,124 @@
+/**
+ * CTA Section
+ * Final call-to-action footer section
+ */
+
+'use client';
+
+import { useState } from 'react';
+import Link from 'next/link';
+import { motion } from 'framer-motion';
+import { Github, Star, Play, ArrowRight } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { DemoCredentialsModal } from './DemoCredentialsModal';
+
+export function CTASection() {
+ const [demoModalOpen, setDemoModalOpen] = useState(false);
+
+ return (
+
+ {/* Background Pattern */}
+
+
+
+
+ {/* Headline */}
+
+ Start Building,{' '}
+
+ Not Boilerplating
+
+
+
+ {/* Subtext */}
+
+ Clone the repository, read the docs, and ship features on day one.{' '}
+ Free forever, MIT licensed.
+
+
+ {/* CTAs */}
+
+
+ {/* Extra Info */}
+
+
+ Need help getting started? Check out the{' '}
+
+ component showcase
+
+ {' '}or explore the{' '}
+
+ admin dashboard demo
+
+ .
+
+
+
+
+
+ {/* Demo Credentials Modal */}
+ setDemoModalOpen(false)}
+ />
+
+ );
+}
diff --git a/frontend/src/components/home/ContextSection.tsx b/frontend/src/components/home/ContextSection.tsx
new file mode 100644
index 0000000..02cf00a
--- /dev/null
+++ b/frontend/src/components/home/ContextSection.tsx
@@ -0,0 +1,59 @@
+/**
+ * Context Section
+ * Explains what the template is and what you get out of the box
+ */
+
+'use client';
+
+import { motion } from 'framer-motion';
+import { CheckCircle2 } from 'lucide-react';
+
+export function ContextSection() {
+ const features = [
+ 'Clone & Deploy in < 5 minutes',
+ '97% Test Coverage (743 tests)',
+ '12+ Documentation Guides',
+ 'Zero Commercial Dependencies',
+ ];
+
+ return (
+
+
+
+
+ What You Get Out of the Box
+
+
+ This isn't a boilerplate generator or a paid SaaS template. It's a complete,
+ production-ready codebase you can clone and customize. Everything you need to build
+ modern web applications without reinventing authentication, authorization, and admin
+ infrastructure.
+
+
+ {/* Feature Badges */}
+
+ {features.map((feature, index) => (
+
+
+ {feature}
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/home/DemoCredentialsModal.tsx b/frontend/src/components/home/DemoCredentialsModal.tsx
new file mode 100644
index 0000000..f258eb4
--- /dev/null
+++ b/frontend/src/components/home/DemoCredentialsModal.tsx
@@ -0,0 +1,141 @@
+/**
+ * Demo Credentials Modal
+ * Displays demo login credentials for testing the live application
+ */
+
+'use client';
+
+import { useState } from 'react';
+import Link from 'next/link';
+import { Copy, Check } from 'lucide-react';
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+} from '@/components/ui/dialog';
+import { Button } from '@/components/ui/button';
+
+interface DemoCredentialsModalProps {
+ open: boolean;
+ onClose: () => void;
+}
+
+export function DemoCredentialsModal({ open, onClose }: DemoCredentialsModalProps) {
+ const [copiedRegular, setCopiedRegular] = useState(false);
+ const [copiedAdmin, setCopiedAdmin] = useState(false);
+
+ const regularCredentials = 'demo@example.com\nDemo123!';
+ const adminCredentials = 'admin@example.com\nAdmin123!';
+
+ const copyToClipboard = async (text: string, type: 'regular' | 'admin') => {
+ try {
+ await navigator.clipboard.writeText(text);
+ if (type === 'regular') {
+ setCopiedRegular(true);
+ setTimeout(() => setCopiedRegular(false), 2000);
+ } else {
+ setCopiedAdmin(true);
+ setTimeout(() => setCopiedAdmin(false), 2000);
+ }
+ } catch (err) {
+ console.error('Failed to copy:', err);
+ }
+ };
+
+ return (
+
+
+
+ Try the Live Demo
+
+ Use these credentials to explore the template's features. Both accounts are pre-configured with sample data.
+
+
+
+
+ {/* Regular User Credentials */}
+
+
+
Regular User
+
copyToClipboard(regularCredentials, 'regular')}
+ className="h-8 gap-2"
+ >
+ {copiedRegular ? (
+
+ ) : (
+
+ )}
+ Copy regular user credentials
+ {copiedRegular ? 'Copied!' : 'Copy'}
+
+
+
+
+ Email:
+ demo@example.com
+
+
+ Password:
+ Demo123!
+
+
+
+ Access settings, organizations, and user features
+
+
+
+ {/* Admin User Credentials */}
+
+
+
Admin User (Superuser)
+
copyToClipboard(adminCredentials, 'admin')}
+ className="h-8 gap-2"
+ >
+ {copiedAdmin ? (
+
+ ) : (
+
+ )}
+ Copy admin user credentials
+ {copiedAdmin ? 'Copied!' : 'Copy'}
+
+
+
+
+ Email:
+ admin@example.com
+
+
+ Password:
+ Admin123!
+
+
+
+ Full admin panel access: user management, analytics, bulk operations
+
+
+
+
+
+
+ Close
+
+
+
+ Go to Login →
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/home/DemoSection.tsx b/frontend/src/components/home/DemoSection.tsx
new file mode 100644
index 0000000..d256151
--- /dev/null
+++ b/frontend/src/components/home/DemoSection.tsx
@@ -0,0 +1,97 @@
+/**
+ * Demo Section
+ * Interactive demo cards showing live features with demo credentials
+ */
+
+'use client';
+
+import Link from 'next/link';
+import { motion } from 'framer-motion';
+import { Play, Layers, ShieldCheck } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+
+const demos = [
+ {
+ icon: Layers,
+ title: 'Component Showcase',
+ description:
+ 'Browse the complete design system, UI components, and interactive examples built with shadcn/ui and TailwindCSS',
+ href: '/dev',
+ cta: 'View Components',
+ variant: 'outline' as const,
+ },
+ {
+ icon: ShieldCheck,
+ title: 'Authentication Flow',
+ description:
+ 'Test the complete auth flow: login, session management, password reset. Full security implementation with JWT and refresh tokens',
+ href: '/login',
+ credentials: 'demo@example.com / Demo123!',
+ cta: 'Try Auth Demo',
+ variant: 'default' as const,
+ },
+ {
+ icon: Play,
+ title: 'Admin Dashboard',
+ description:
+ 'Experience the admin panel with user management, real-time analytics charts, bulk operations, and session monitoring',
+ href: '/admin',
+ credentials: 'admin@example.com / Admin123!',
+ cta: 'Launch Admin',
+ variant: 'outline' as const,
+ },
+];
+
+export function DemoSection() {
+ return (
+
+
+ See It In Action
+
+ Explore the template's capabilities with live demos. Login with demo credentials to test features.
+
+
+
+
+ {demos.map((demo, index) => (
+
+ {/* Icon */}
+
+
+
+
+ {demo.title}
+
+ {demo.description}
+
+
+ {demo.credentials && (
+
+
Demo Credentials:
+
{demo.credentials}
+
+ )}
+
+
+ {demo.cta} →
+
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/src/components/home/FeatureCard.tsx b/frontend/src/components/home/FeatureCard.tsx
new file mode 100644
index 0000000..d2e3a3b
--- /dev/null
+++ b/frontend/src/components/home/FeatureCard.tsx
@@ -0,0 +1,63 @@
+/**
+ * Feature Card
+ * Reusable feature card component with icon, title, description, and CTA link
+ */
+
+'use client';
+
+import Link from 'next/link';
+import { motion } from 'framer-motion';
+import { ArrowRight, LucideIcon } from 'lucide-react';
+
+interface FeatureCardProps {
+ icon: LucideIcon;
+ title: string;
+ description: string;
+ highlight: string;
+ ctaText: string;
+ ctaHref: string;
+}
+
+export function FeatureCard({
+ icon: Icon,
+ title,
+ description,
+ highlight,
+ ctaText,
+ ctaHref,
+}: FeatureCardProps) {
+ return (
+
+ {/* Icon with Gradient Background */}
+
+
+
+
+ {/* Title */}
+ {title}
+
+ {/* Highlight Badge */}
+
+
+ {highlight}
+
+
+
+ {/* Description */}
+ {description}
+
+ {/* CTA Link */}
+
+ {ctaText}
+
+
+
+ );
+}
diff --git a/frontend/src/components/home/FeatureGrid.tsx b/frontend/src/components/home/FeatureGrid.tsx
new file mode 100644
index 0000000..993f31a
--- /dev/null
+++ b/frontend/src/components/home/FeatureGrid.tsx
@@ -0,0 +1,117 @@
+/**
+ * Feature Grid
+ * Grid layout displaying 6 main features with stagger animation
+ */
+
+'use client';
+
+import { motion } from 'framer-motion';
+import { Shield, Users, BarChart3, BookOpen, Server, Code } from 'lucide-react';
+import { FeatureCard } from './FeatureCard';
+
+const features = [
+ {
+ icon: Shield,
+ title: 'Authentication & Security',
+ description:
+ 'JWT authentication with refresh tokens, session management, password reset flow, rate limiting, CSRF protection, and comprehensive security tests preventing common attacks (CVE-2015-9235, session hijacking)',
+ highlight: 'Battle-tested security',
+ ctaText: 'View Auth Flow',
+ ctaHref: '/login',
+ },
+ {
+ icon: Users,
+ title: 'Multi-Tenant Organizations',
+ description:
+ 'Complete organization system with 3-tier RBAC (Owner/Admin/Member). Invite members, manage permissions, and scope data access per organization—all batteries included',
+ highlight: 'Multi-tenancy built-in',
+ ctaText: 'See Organizations',
+ ctaHref: '/admin/organizations',
+ },
+ {
+ icon: BarChart3,
+ title: 'Admin Dashboard',
+ description:
+ 'Full-featured admin panel with user management, real-time analytics charts, bulk operations, session monitoring, and role-based access controls',
+ highlight: 'Enterprise-ready admin',
+ ctaText: 'Try Admin Panel',
+ ctaHref: '/admin',
+ },
+ {
+ icon: BookOpen,
+ title: 'Complete Documentation',
+ description:
+ '12+ documentation guides covering architecture, design system, testing patterns, deployment, and AI code generation guidelines. Interactive API docs with Swagger and ReDoc',
+ highlight: 'Developer-first docs',
+ ctaText: 'Browse Docs',
+ ctaHref: 'https://github.com/your-org/fast-next-template#documentation',
+ },
+ {
+ icon: Server,
+ title: 'Production Ready',
+ description:
+ 'Docker deployment configs, database migrations with Alembic helpers, connection pooling, health checks, monitoring setup, and production security headers',
+ highlight: 'Deploy with confidence',
+ ctaText: 'Deployment Guide',
+ ctaHref: 'https://github.com/your-org/fast-next-template#deployment',
+ },
+ {
+ icon: Code,
+ title: 'Developer Experience',
+ description:
+ 'Auto-generated TypeScript API client from OpenAPI spec, hot reload in development, migration helpers (python migrate.py auto), VS Code settings, and comprehensive component library',
+ highlight: 'Delightful DX',
+ ctaText: 'Explore Components',
+ ctaHref: '/dev',
+ },
+];
+
+const containerVariants = {
+ hidden: { opacity: 0 },
+ show: {
+ opacity: 1,
+ transition: {
+ staggerChildren: 0.15,
+ },
+ },
+};
+
+const itemVariants = {
+ hidden: { opacity: 0, y: 20 },
+ show: { opacity: 1, y: 0 },
+};
+
+export function FeatureGrid() {
+ return (
+
+
+
+ Comprehensive Features, No Assembly Required
+
+
+ Everything you need to build production-grade web applications. Clone, customize, and ship.
+
+
+
+
+ {features.map((feature) => (
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/src/components/home/Header.tsx b/frontend/src/components/home/Header.tsx
new file mode 100644
index 0000000..37149ac
--- /dev/null
+++ b/frontend/src/components/home/Header.tsx
@@ -0,0 +1,155 @@
+/**
+ * Homepage Header
+ * Navigation header for the landing page with demo credentials modal
+ */
+
+'use client';
+
+import { useState } from 'react';
+import Link from 'next/link';
+import { Menu, X, Github, Star } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { DemoCredentialsModal } from './DemoCredentialsModal';
+import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
+
+export function Header() {
+ const [demoModalOpen, setDemoModalOpen] = useState(false);
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
+
+ const navLinks = [
+ { href: '/dev', label: 'Components' },
+ { href: '/admin', label: 'Admin Demo' },
+ ];
+
+ return (
+ <>
+
+
+ {/* Demo Credentials Modal */}
+ setDemoModalOpen(false)}
+ />
+ >
+ );
+}
diff --git a/frontend/src/components/home/HeroSection.tsx b/frontend/src/components/home/HeroSection.tsx
new file mode 100644
index 0000000..b501fa0
--- /dev/null
+++ b/frontend/src/components/home/HeroSection.tsx
@@ -0,0 +1,150 @@
+/**
+ * Hero Section
+ * Main hero section with headline, subheadline, CTAs, and gradient background
+ */
+
+'use client';
+
+import { useState } from 'react';
+import Link from 'next/link';
+import { motion } from 'framer-motion';
+import { ArrowRight, Github, Play } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { DemoCredentialsModal } from './DemoCredentialsModal';
+
+export function HeroSection() {
+ const [demoModalOpen, setDemoModalOpen] = useState(false);
+
+ return (
+
+ {/* Gradient Background */}
+
+
+
+
+
+
+ {/* Badge */}
+
+
+
+ MIT Licensed
+ •
+ 97% Test Coverage
+ •
+ Production Ready
+
+
+
+ {/* Headline */}
+
+ Everything You Need to Build
+
+ Modern Web Applications
+
+
+
+ {/* Subheadline */}
+
+ Production-ready FastAPI + Next.js template with authentication, multi-tenancy, and
+ comprehensive admin panel. Built by developers, for developers.{' '}
+ Start building features on day one.
+
+
+ {/* CTAs */}
+
+ setDemoModalOpen(true)}
+ className="gap-2 text-base group"
+ >
+
+ Try Live Demo
+
+
+
+
+ View on GitHub
+
+
+
+
+
+ Explore Components
+
+
+
+
+
+ {/* Quick Stats */}
+
+
+ 97%
+ Test Coverage
+
+
+
+ 743
+ Passing Tests
+
+
+
+ 0
+ Flaky Tests
+
+
+
+
+
+ {/* Demo Credentials Modal */}
+ setDemoModalOpen(false)}
+ />
+
+ );
+}
diff --git a/frontend/src/components/home/PhilosophySection.tsx b/frontend/src/components/home/PhilosophySection.tsx
new file mode 100644
index 0000000..063a771
--- /dev/null
+++ b/frontend/src/components/home/PhilosophySection.tsx
@@ -0,0 +1,103 @@
+/**
+ * Philosophy Section
+ * "For Developers, By Developers" section explaining why this template exists
+ */
+
+'use client';
+
+import { motion } from 'framer-motion';
+import { X, Check } from 'lucide-react';
+
+const wontFind = [
+ 'Vendor lock-in to specific services',
+ 'Hidden costs or upgrade prompts',
+ 'Poorly documented "magic"',
+ 'Outdated dependencies',
+];
+
+const willFind = [
+ 'Production patterns that actually work',
+ 'Comprehensive test coverage (not aspirational)',
+ 'Clear, honest documentation',
+ 'Active development and improvements',
+];
+
+export function PhilosophySection() {
+ return (
+
+
+
+
+ Why This Template Exists
+
+
+
+ We built this template after rebuilding the same authentication, authorization, and
+ admin infrastructure for the fifth time. Instead of yet another tutorial or boilerplate
+ generator, we created a complete, tested, documented codebase that you can clone and
+ customize.
+
+
+ No vendor lock-in. No subscriptions. No license restrictions.
+
+
+ Just clean, modern code with patterns that scale. MIT licensed forever.
+
+
+
+
+
+ {/* What You Won't Find */}
+
+
+
+ What You Won't Find Here
+
+
+ {wontFind.map((item) => (
+
+
+ {item}
+
+ ))}
+
+
+
+ {/* What You Will Find */}
+
+
+
+ What You Will Find
+
+
+ {willFind.map((item) => (
+
+
+ {item}
+
+ ))}
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/home/QuickStartCode.tsx b/frontend/src/components/home/QuickStartCode.tsx
new file mode 100644
index 0000000..cbe0f1b
--- /dev/null
+++ b/frontend/src/components/home/QuickStartCode.tsx
@@ -0,0 +1,101 @@
+/**
+ * Quick Start Code Block
+ * Code snippet showing quick start commands with copy functionality
+ */
+
+'use client';
+
+import { useState } from 'react';
+import { motion } from 'framer-motion';
+import { Check, Copy } from 'lucide-react';
+import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
+import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
+import { Button } from '@/components/ui/button';
+
+const codeString = `# Clone and start with Docker
+git clone https://github.com/your-org/fast-next-template.git
+cd fast-next-template
+docker-compose up
+
+# Or set up locally
+cd backend && python -m venv .venv && source .venv/bin/activate
+pip install -r requirements.txt
+cd ../frontend && npm install`;
+
+export function QuickStartCode() {
+ const [copied, setCopied] = useState(false);
+
+ const copyToClipboard = async () => {
+ try {
+ await navigator.clipboard.writeText(codeString);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ } catch (err) {
+ console.error('Failed to copy:', err);
+ }
+ };
+
+ return (
+
+
+
+
5-Minute Setup
+
+ Clone, run, and start building. It's that simple.
+
+
+
+
+ {/* Header with Copy Button */}
+
+
+
+ bash
+
+
+ {copied ? (
+ <>
+
+ Copied!
+ >
+ ) : (
+ <>
+
+ Copy
+ >
+ )}
+
+
+
+ {/* Code Block */}
+
+
+ {codeString}
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/home/StatsSection.tsx b/frontend/src/components/home/StatsSection.tsx
new file mode 100644
index 0000000..af34b2f
--- /dev/null
+++ b/frontend/src/components/home/StatsSection.tsx
@@ -0,0 +1,134 @@
+/**
+ * Stats Section
+ * Animated statistics with counters
+ */
+
+'use client';
+
+import { useEffect, useState } from 'react';
+import { motion, useInView } from 'framer-motion';
+import { useRef } from 'react';
+import { CheckCircle2, TestTube, Zap, FileCode } from 'lucide-react';
+
+interface Stat {
+ icon: React.ComponentType<{ className?: string }>;
+ value: number;
+ suffix: string;
+ label: string;
+ description: string;
+}
+
+const stats: Stat[] = [
+ {
+ icon: Zap,
+ value: 97,
+ suffix: '%',
+ label: 'Test Coverage',
+ description: 'Comprehensive testing across backend and frontend',
+ },
+ {
+ icon: TestTube,
+ value: 743,
+ suffix: '',
+ label: 'Passing Tests',
+ description: 'Backend, frontend unit, and E2E tests',
+ },
+ {
+ icon: CheckCircle2,
+ value: 0,
+ suffix: '',
+ label: 'Flaky Tests',
+ description: 'Production-stable test suite',
+ },
+ {
+ icon: FileCode,
+ value: 30,
+ suffix: '+',
+ label: 'API Endpoints',
+ description: 'Fully documented with OpenAPI',
+ },
+];
+
+function AnimatedCounter({ value, suffix }: { value: number; suffix: string }) {
+ const [count, setCount] = useState(0);
+ const ref = useRef(null);
+ const isInView = useInView(ref, { once: true, margin: '-100px' });
+
+ useEffect(() => {
+ if (!isInView) return;
+
+ const duration = 2000; // 2 seconds
+ const steps = 60;
+ const increment = value / steps;
+ let current = 0;
+
+ const timer = setInterval(() => {
+ current += increment;
+ if (current >= value) {
+ setCount(value);
+ clearInterval(timer);
+ } else {
+ setCount(Math.floor(current));
+ }
+ }, duration / steps);
+
+ return () => clearInterval(timer);
+ }, [isInView, value]);
+
+ return (
+
+ {count}
+ {suffix}
+
+ );
+}
+
+export function StatsSection() {
+ return (
+
+
+ Built with Quality in Mind
+
+ Not just another template. Comprehensive testing, documentation, and production-ready patterns.
+
+
+
+
+ {stats.map((stat, index) => (
+
+ {/* Icon */}
+
+
+ {/* Animated Counter */}
+
+
+ {/* Label */}
+
+
{stat.label}
+
{stat.description}
+
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/src/components/home/TechStackSection.tsx b/frontend/src/components/home/TechStackSection.tsx
new file mode 100644
index 0000000..622d68d
--- /dev/null
+++ b/frontend/src/components/home/TechStackSection.tsx
@@ -0,0 +1,104 @@
+/**
+ * Tech Stack Section
+ * Displays technology logos/badges with tooltips
+ */
+
+'use client';
+
+import { motion } from 'framer-motion';
+
+interface Tech {
+ name: string;
+ description: string;
+ color: string;
+}
+
+const technologies: Tech[] = [
+ {
+ name: 'FastAPI',
+ description: 'Async Python web framework, auto-docs, type hints',
+ color: 'from-teal-500 to-green-600',
+ },
+ {
+ name: 'Next.js 15',
+ description: 'React 19, App Router, Server Components',
+ color: 'from-slate-900 to-slate-700',
+ },
+ {
+ name: 'PostgreSQL',
+ description: 'Reliable, scalable SQL database',
+ color: 'from-blue-600 to-blue-800',
+ },
+ {
+ name: 'TypeScript',
+ description: 'End-to-end type safety',
+ color: 'from-blue-500 to-blue-700',
+ },
+ {
+ name: 'Docker',
+ description: 'Containerized deployment',
+ color: 'from-blue-400 to-blue-600',
+ },
+ {
+ name: 'TailwindCSS',
+ description: 'Utility-first styling with OKLCH colors',
+ color: 'from-cyan-500 to-blue-500',
+ },
+ {
+ name: 'shadcn/ui',
+ description: 'Accessible component library (New York variant)',
+ color: 'from-slate-800 to-slate-600',
+ },
+ {
+ name: 'Playwright',
+ description: 'Reliable E2E testing (zero flaky tests)',
+ color: 'from-green-600 to-emerald-700',
+ },
+];
+
+export function TechStackSection() {
+ return (
+
+
+
+ Modern, Type-Safe, Production-Grade Stack
+
+
+ Built with the best tools for full-stack development. Async architecture, type safety, and developer experience.
+
+
+
+
+ {technologies.map((tech, index) => (
+
+
+ {/* Tech Badge */}
+
+ {tech.name}
+
+
+ {/* Hover Tooltip */}
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/src/hooks/usePrefersReducedMotion.ts b/frontend/src/hooks/usePrefersReducedMotion.ts
new file mode 100644
index 0000000..b097012
--- /dev/null
+++ b/frontend/src/hooks/usePrefersReducedMotion.ts
@@ -0,0 +1,33 @@
+/**
+ * Hook to detect if user prefers reduced motion
+ * Respects prefers-reduced-motion media query for accessibility
+ */
+
+import { useEffect, useState } from 'react';
+
+export function usePrefersReducedMotion(): boolean {
+ const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
+
+ useEffect(() => {
+ // Check if window is defined (SSR safety)
+ if (typeof window === 'undefined') {
+ return;
+ }
+
+ const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
+ setPrefersReducedMotion(mediaQuery.matches);
+
+ // Listen for changes
+ const handleChange = (event: MediaQueryListEvent) => {
+ setPrefersReducedMotion(event.matches);
+ };
+
+ mediaQuery.addEventListener('change', handleChange);
+
+ return () => {
+ mediaQuery.removeEventListener('change', handleChange);
+ };
+ }, []);
+
+ return prefersReducedMotion;
+}