Initial commit
This commit is contained in:
30
src/App.js
Normal file
30
src/App.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import Header from './components/Header';
|
||||
import Hero from './components/Hero';
|
||||
import Features from './components/Features';
|
||||
import EverythingYouNeed from './components/EverythingYouNeed';
|
||||
import DeploySection from './components/DeploySection';
|
||||
import CoursesSection from './components/CoursesSection';
|
||||
import EnterpriseSection from './components/EnterpriseSection';
|
||||
import LivePreview from './components/LivePreview';
|
||||
import SupportSection from './components/SupportSection';
|
||||
import Footer from './components/Footer';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<Header />
|
||||
<Hero />
|
||||
<Features />
|
||||
<EverythingYouNeed />
|
||||
<DeploySection />
|
||||
<CoursesSection />
|
||||
<EnterpriseSection />
|
||||
<LivePreview />
|
||||
<SupportSection />
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
59
src/components/CoursesSection.js
Normal file
59
src/components/CoursesSection.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
function CoursesSection() {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="section-padding bg-nest-light-gray">
|
||||
<div className="container-custom">
|
||||
<div className="bg-white p-12 rounded-lg shadow-sm">
|
||||
<h3 className="text-3xl font-bold mb-6">
|
||||
Official NestJS Courses
|
||||
</h3>
|
||||
<p className="text-nest-gray mb-8 leading-relaxed max-w-2xl">
|
||||
Learn from the creators of NestJS. Our comprehensive courses will teach you everything you need to know to build production-ready applications.
|
||||
</p>
|
||||
<button className="btn-primary">
|
||||
Get started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="section-padding bg-nest-light-gray"
|
||||
>
|
||||
<div className="container-custom">
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.2, 0.8)}
|
||||
className="bg-white p-12 rounded-lg shadow-sm"
|
||||
>
|
||||
<h3 className="text-3xl font-bold mb-6">
|
||||
Official NestJS Courses
|
||||
</h3>
|
||||
<p className="text-nest-gray mb-8 leading-relaxed max-w-2xl">
|
||||
Learn from the creators of NestJS. Our comprehensive courses will teach you everything you need to know to build production-ready applications.
|
||||
</p>
|
||||
<button className="btn-primary">
|
||||
Get started
|
||||
</button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default CoursesSection;
|
||||
94
src/components/DeploySection.js
Normal file
94
src/components/DeploySection.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
function DeploySection() {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="section-padding">
|
||||
<div className="container-custom">
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{/* Deploy Card */}
|
||||
<div className="bg-nest-dark text-white p-12 rounded-lg">
|
||||
<h3 className="text-3xl font-bold mb-6">
|
||||
Deploy, now!
|
||||
</h3>
|
||||
<p className="text-gray-300 mb-8 leading-relaxed">
|
||||
Deploy your Nest application to the cloud with a single command using our official deployment tools.
|
||||
</p>
|
||||
<button className="btn-primary">
|
||||
Get started
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Explore Card */}
|
||||
<div className="bg-nest-red text-white p-12 rounded-lg">
|
||||
<h3 className="text-3xl font-bold mb-6">
|
||||
Explore your graph
|
||||
</h3>
|
||||
<p className="text-red-100 mb-8 leading-relaxed">
|
||||
Visualize your application's dependency graph and understand the relationships between modules.
|
||||
</p>
|
||||
<button className="bg-white text-nest-red px-6 py-3 rounded-lg font-medium hover:bg-gray-100 transition-colors">
|
||||
Explore
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="section-padding"
|
||||
>
|
||||
<div className="container-custom">
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{/* Deploy Card */}
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.2, 0.8)}
|
||||
className="bg-nest-dark text-white p-12 rounded-lg"
|
||||
>
|
||||
<h3 className="text-3xl font-bold mb-6">
|
||||
Deploy, now!
|
||||
</h3>
|
||||
<p className="text-gray-300 mb-8 leading-relaxed">
|
||||
Deploy your Nest application to the cloud with a single command using our official deployment tools.
|
||||
</p>
|
||||
<button className="btn-primary">
|
||||
Get started
|
||||
</button>
|
||||
</motion.div>
|
||||
|
||||
{/* Explore Card */}
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.4, 0.8)}
|
||||
className="bg-nest-red text-white p-12 rounded-lg"
|
||||
>
|
||||
<h3 className="text-3xl font-bold mb-6">
|
||||
Explore your graph
|
||||
</h3>
|
||||
<p className="text-red-100 mb-8 leading-relaxed">
|
||||
Visualize your application's dependency graph and understand the relationships between modules.
|
||||
</p>
|
||||
<button className="bg-white text-nest-red px-6 py-3 rounded-lg font-medium hover:bg-gray-100 transition-colors">
|
||||
Explore
|
||||
</button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default DeploySection;
|
||||
80
src/components/EnterpriseSection.js
Normal file
80
src/components/EnterpriseSection.js
Normal file
@@ -0,0 +1,80 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
function EnterpriseSection() {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="section-padding bg-nest-red text-white">
|
||||
<div className="container-custom">
|
||||
<div className="flex flex-col lg:flex-row items-center gap-12">
|
||||
<div className="lg:w-1/3">
|
||||
<img
|
||||
src="https://nestjs.com/img/cat-enterprise.png"
|
||||
alt="NestJS Enterprise Cat"
|
||||
className="w-full max-w-sm mx-auto"
|
||||
/>
|
||||
</div>
|
||||
<div className="lg:w-2/3">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
||||
The open source platform designed for the future. Build enterprise.
|
||||
</h2>
|
||||
<p className="text-xl mb-8 leading-relaxed text-red-100">
|
||||
A complete development kit for building scalable server-side applications. Everything you need to take your Node.js app from prototype to enterprise.
|
||||
</p>
|
||||
<button className="bg-white text-nest-red px-8 py-4 rounded-lg font-medium text-lg hover:bg-gray-100 transition-colors">
|
||||
Contact us
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="section-padding bg-nest-red text-white"
|
||||
>
|
||||
<div className="container-custom">
|
||||
<div className="flex flex-col lg:flex-row items-center gap-12">
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.2, 0.8)}
|
||||
className="lg:w-1/3"
|
||||
>
|
||||
<img
|
||||
src="https://nestjs.com/img/cat-enterprise.png"
|
||||
alt="NestJS Enterprise Cat"
|
||||
className="w-full max-w-sm mx-auto"
|
||||
/>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.4, 0.8)}
|
||||
className="lg:w-2/3"
|
||||
>
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
||||
The open source platform designed for the future. Build enterprise.
|
||||
</h2>
|
||||
<p className="text-xl mb-8 leading-relaxed text-red-100">
|
||||
A complete development kit for building scalable server-side applications. Everything you need to take your Node.js app from prototype to enterprise.
|
||||
</p>
|
||||
<button className="bg-white text-nest-red px-8 py-4 rounded-lg font-medium text-lg hover:bg-gray-100 transition-colors">
|
||||
Contact us
|
||||
</button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default EnterpriseSection;
|
||||
135
src/components/EverythingYouNeed.js
Normal file
135
src/components/EverythingYouNeed.js
Normal file
@@ -0,0 +1,135 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
import { Package, Zap, Globe, Settings, File, Eye, Users, TrendingUp } from 'lucide-react';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
function EverythingYouNeed() {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: Package,
|
||||
title: "POWERFUL CLI",
|
||||
description: "Nest CLI is a command-line interface tool that helps you to initialize, develop, and maintain your Nest applications."
|
||||
},
|
||||
{
|
||||
icon: Zap,
|
||||
title: "DEPENDENCY INJECTION",
|
||||
description: "Built-in inversion of control (IoC) container with a powerful dependency injection system."
|
||||
},
|
||||
{
|
||||
icon: Globe,
|
||||
title: "MICROSERVICES READY",
|
||||
description: "Build microservices with different transport layers like TCP, Redis, NATS, RabbitMQ, and more."
|
||||
},
|
||||
{
|
||||
icon: Settings,
|
||||
title: "TESTING UTILITIES",
|
||||
description: "Comes with dedicated testing utilities that make it easy to test your applications."
|
||||
},
|
||||
{
|
||||
icon: File,
|
||||
title: "BUILT-IN DOCUMENTATION",
|
||||
description: "Automatically generate OpenAPI documentation for your REST APIs using decorators."
|
||||
},
|
||||
{
|
||||
icon: Eye,
|
||||
title: "GRAPHQL SUPPORT",
|
||||
description: "First-class support for GraphQL with code-first and schema-first approaches."
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: "WEBSOCKETS",
|
||||
description: "Real-time applications with WebSockets support and Socket.io integration."
|
||||
},
|
||||
{
|
||||
icon: TrendingUp,
|
||||
title: "PERFORMANCE",
|
||||
description: "High performance thanks to Fastify integration and other performance optimizations."
|
||||
}
|
||||
];
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="section-padding bg-white">
|
||||
<div className="container-custom">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
||||
Everything you need...
|
||||
</h2>
|
||||
<p className="text-xl text-nest-gray max-w-3xl mx-auto">
|
||||
Built with modern technologies and best practices for enterprise applications.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{features.map((feature, index) => {
|
||||
const Icon = feature.icon;
|
||||
return (
|
||||
<div key={index} className="feature-card text-center">
|
||||
<Icon className="w-12 h-12 mx-auto mb-4 text-nest-red" />
|
||||
<h3 className="font-bold text-sm mb-3 text-nest-dark">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-sm text-nest-gray leading-relaxed">
|
||||
{feature.description}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="section-padding bg-white"
|
||||
>
|
||||
<div className="container-custom">
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.2, 0.8)}
|
||||
className="text-center mb-16"
|
||||
>
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
||||
Everything you need...
|
||||
</h2>
|
||||
<p className="text-xl text-nest-gray max-w-3xl mx-auto">
|
||||
Built with modern technologies and best practices for enterprise applications.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{features.map((feature, index) => {
|
||||
const Icon = feature.icon;
|
||||
return (
|
||||
<motion.div
|
||||
key={index}
|
||||
{...fadeUpPreset(0.3 + (index * 0.05), 0.6)}
|
||||
className="feature-card text-center"
|
||||
>
|
||||
<Icon className="w-12 h-12 mx-auto mb-4 text-nest-red" />
|
||||
<h3 className="font-bold text-sm mb-3 text-nest-dark">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-sm text-nest-gray leading-relaxed">
|
||||
{feature.description}
|
||||
</p>
|
||||
</motion.div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default EverythingYouNeed;
|
||||
100
src/components/Features.js
Normal file
100
src/components/Features.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
function Features() {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: (
|
||||
<svg className="w-16 h-16 mx-auto mb-6" viewBox="0 0 100 100" fill="none">
|
||||
<path d="M20 20h60v60H20z" stroke="#333" strokeWidth="2" fill="none"/>
|
||||
<path d="M30 30h40v40H30z" stroke="#333" strokeWidth="2" fill="none"/>
|
||||
<path d="M40 40h20v20H40z" stroke="#333" strokeWidth="2" fill="none"/>
|
||||
</svg>
|
||||
),
|
||||
title: "EXTENSIBLE",
|
||||
description: "Provides unparalleled flexibility through its meticulously crafted modular architecture."
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<svg className="w-16 h-16 mx-auto mb-6" viewBox="0 0 100 100" fill="none">
|
||||
<path d="M50 10L80 30v40L50 90L20 70V30z" stroke="#e0234e" strokeWidth="2" fill="none"/>
|
||||
<circle cx="50" cy="50" r="8" fill="#e0234e"/>
|
||||
<path d="M35 35l30 30M65 35L35 65" stroke="#e0234e" strokeWidth="2"/>
|
||||
</svg>
|
||||
),
|
||||
title: "VERSATILE",
|
||||
description: "Serves as a robust, elegant, and well-structured foundation for all kinds of server-side applications."
|
||||
},
|
||||
{
|
||||
icon: (
|
||||
<svg className="w-16 h-16 mx-auto mb-6" viewBox="0 0 100 100" fill="none">
|
||||
<path d="M50 10L70 30L50 50L30 30z" fill="#333"/>
|
||||
<path d="M30 50L50 70L70 50L50 30z" fill="#666"/>
|
||||
<path d="M50 70L70 90L50 110L30 90z" fill="#333"/>
|
||||
</svg>
|
||||
),
|
||||
title: "PROGRESSIVE",
|
||||
description: "Introduces design patterns and well-established solutions to the Node.js landscape."
|
||||
}
|
||||
];
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="section-padding bg-nest-light-gray">
|
||||
<div className="container-custom">
|
||||
<div className="grid md:grid-cols-3 gap-12">
|
||||
{features.map((feature, index) => (
|
||||
<div key={index} className="text-center">
|
||||
{feature.icon}
|
||||
<h3 className="text-nest-red font-bold text-lg mb-4">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-nest-gray leading-relaxed">
|
||||
{feature.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="section-padding bg-nest-light-gray"
|
||||
>
|
||||
<div className="container-custom">
|
||||
<div className="grid md:grid-cols-3 gap-12">
|
||||
{features.map((feature, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
{...fadeUpPreset(index * 0.1, 0.8)}
|
||||
className="text-center"
|
||||
>
|
||||
{feature.icon}
|
||||
<h3 className="text-nest-red font-bold text-lg mb-4">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-nest-gray leading-relaxed">
|
||||
{feature.description}
|
||||
</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Features;
|
||||
61
src/components/Footer.js
Normal file
61
src/components/Footer.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import React from 'react';
|
||||
import { Github, X } from 'lucide-react';
|
||||
|
||||
function Footer() {
|
||||
return (
|
||||
<footer className="bg-nest-light-gray py-12">
|
||||
<div className="container-custom">
|
||||
<div className="text-center">
|
||||
{/* Social Links */}
|
||||
<div className="flex justify-center space-x-6 mb-8">
|
||||
<a href="#" className="text-nest-gray hover:text-nest-red transition-colors">
|
||||
<Github className="h-6 w-6" />
|
||||
</a>
|
||||
<a href="#" className="text-nest-gray hover:text-nest-red transition-colors">
|
||||
<X className="h-6 w-6" />
|
||||
</a>
|
||||
<a href="#" className="text-nest-gray hover:text-nest-red transition-colors">
|
||||
<svg className="h-6 w-6" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Footer Text */}
|
||||
<div className="space-y-2 text-sm text-nest-gray">
|
||||
<p>Released under the MIT License</p>
|
||||
<p>
|
||||
Official NestJS Consulting{' '}
|
||||
<a href="#" className="text-nest-red hover:underline">
|
||||
Trilon.io
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Copyright © 2017- 2024{' '}
|
||||
<a href="#" className="text-nest-red hover:underline">
|
||||
Kamil Mysliwiec
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Designed by{' '}
|
||||
<a href="#" className="text-nest-red hover:underline">
|
||||
Jakub Staron
|
||||
</a>
|
||||
, hosted by{' '}
|
||||
<a href="#" className="text-nest-red hover:underline">
|
||||
Netlify
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="#" className="text-nest-red hover:underline">
|
||||
中文说明
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
export default Footer;
|
||||
88
src/components/Header.js
Normal file
88
src/components/Header.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Menu, X, ChevronDown, Github } from 'lucide-react';
|
||||
|
||||
function Header() {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
const [isResourcesOpen, setIsResourcesOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<header className="fixed top-0 left-0 right-0 z-50 bg-black/90 backdrop-blur-sm">
|
||||
<div className="container-custom">
|
||||
<div className="flex items-center justify-between h-16">
|
||||
{/* Logo */}
|
||||
<div className="flex items-center">
|
||||
<img
|
||||
src="https://nestjs.com/img/logo-small.svg"
|
||||
alt="NestJS"
|
||||
className="h-8 w-8"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<nav className="hidden md:flex items-center space-x-8">
|
||||
<a href="#" className="text-white hover:text-nest-red transition-colors">
|
||||
DOCUMENTATION
|
||||
</a>
|
||||
<a href="#" className="text-white hover:text-nest-red transition-colors">
|
||||
ENTERPRISE
|
||||
</a>
|
||||
<div className="relative">
|
||||
<button
|
||||
className="flex items-center text-white hover:text-nest-red transition-colors"
|
||||
onClick={() => setIsResourcesOpen(!isResourcesOpen)}
|
||||
>
|
||||
<span className="bg-nest-red text-white text-xs px-2 py-1 rounded mr-2">
|
||||
NEW
|
||||
</span>
|
||||
RESOURCES
|
||||
<ChevronDown className="ml-1 h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Social Links */}
|
||||
<div className="hidden md:flex items-center space-x-4">
|
||||
<a href="#" className="text-white hover:text-nest-red transition-colors">
|
||||
<Github className="h-5 w-5" />
|
||||
</a>
|
||||
<a href="#" className="text-white hover:text-nest-red transition-colors">
|
||||
<X className="h-5 w-5" />
|
||||
</a>
|
||||
<a href="#" className="text-white hover:text-nest-red transition-colors">
|
||||
<svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Mobile menu button */}
|
||||
<button
|
||||
className="md:hidden text-white"
|
||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||
>
|
||||
{isMenuOpen ? <X className="h-6 w-6" /> : <Menu className="h-6 w-6" />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation */}
|
||||
{isMenuOpen && (
|
||||
<div className="md:hidden bg-black/95 absolute top-16 left-0 right-0 p-4">
|
||||
<nav className="flex flex-col space-y-4">
|
||||
<a href="#" className="text-white hover:text-nest-red transition-colors">
|
||||
DOCUMENTATION
|
||||
</a>
|
||||
<a href="#" className="text-white hover:text-nest-red transition-colors">
|
||||
ENTERPRISE
|
||||
</a>
|
||||
<a href="#" className="text-white hover:text-nest-red transition-colors">
|
||||
RESOURCES
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
export default Header;
|
||||
82
src/components/Hero.js
Normal file
82
src/components/Hero.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
import { Github } from 'lucide-react';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
function Hero() {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="relative min-h-screen bg-black flex items-center justify-center overflow-hidden">
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center bg-no-repeat opacity-30"
|
||||
style={{ backgroundImage: "url('https://nestjs.com/img/hero-bg.jpg')" }}
|
||||
/>
|
||||
<div className="relative z-10 container-custom text-center text-white">
|
||||
<h1 className="text-5xl md:text-7xl font-bold mb-6">
|
||||
Hello, nest!
|
||||
</h1>
|
||||
<p className="text-xl md:text-2xl mb-12 max-w-3xl mx-auto leading-relaxed">
|
||||
A progressive Node.js framework for building efficient, reliable and scalable server-side applications.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<button className="btn-primary text-lg px-8 py-4">
|
||||
Documentation
|
||||
</button>
|
||||
<button className="btn-secondary text-lg px-8 py-4 flex items-center justify-center gap-2">
|
||||
<Github className="h-5 w-5" />
|
||||
Source code
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 0.8)}
|
||||
className="relative min-h-screen bg-black flex items-center justify-center overflow-hidden"
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 bg-cover bg-center bg-no-repeat opacity-30"
|
||||
style={{ backgroundImage: "url('https://nestjs.com/img/hero-bg.jpg')" }}
|
||||
/>
|
||||
<div className="relative z-10 container-custom text-center text-white">
|
||||
<motion.h1
|
||||
{...fadeUpPreset(0.2, 0.8)}
|
||||
className="text-5xl md:text-7xl font-bold mb-6"
|
||||
>
|
||||
Hello, nest!
|
||||
</motion.h1>
|
||||
<motion.p
|
||||
{...fadeUpPreset(0.4, 0.8)}
|
||||
className="text-xl md:text-2xl mb-12 max-w-3xl mx-auto leading-relaxed"
|
||||
>
|
||||
A progressive Node.js framework for building efficient, reliable and scalable server-side applications.
|
||||
</motion.p>
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.6, 0.8)}
|
||||
className="flex flex-col sm:flex-row gap-4 justify-center"
|
||||
>
|
||||
<button className="btn-primary text-lg px-8 py-4">
|
||||
Documentation
|
||||
</button>
|
||||
<button className="btn-secondary text-lg px-8 py-4 flex items-center justify-center gap-2">
|
||||
<Github className="h-5 w-5" />
|
||||
Source code
|
||||
</button>
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Hero;
|
||||
99
src/components/LivePreview.js
Normal file
99
src/components/LivePreview.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
function LivePreview() {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="section-padding bg-nest-dark text-white">
|
||||
<div className="container-custom text-center">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
||||
Live preview
|
||||
</h2>
|
||||
<p className="text-xl text-gray-300 mb-12 max-w-2xl mx-auto">
|
||||
See NestJS in action with our interactive examples and live coding environment.
|
||||
</p>
|
||||
<div className="bg-black/50 rounded-lg p-8 max-w-4xl mx-auto">
|
||||
<div className="text-left">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<div className="w-3 h-3 bg-red-500 rounded-full"></div>
|
||||
<div className="w-3 h-3 bg-yellow-500 rounded-full"></div>
|
||||
<div className="w-3 h-3 bg-green-500 rounded-full"></div>
|
||||
</div>
|
||||
<div className="font-mono text-sm text-gray-300">
|
||||
<div className="text-blue-400">import</div>
|
||||
<div className="ml-4">{'{ Controller, Get }'} <span className="text-blue-400">from</span> <span className="text-green-400">'@nestjs/common'</span>;</div>
|
||||
<div className="mt-4 text-yellow-400">@Controller()</div>
|
||||
<div className="text-blue-400">export class</div>
|
||||
<div className="ml-4">AppController {'{'}</div>
|
||||
<div className="ml-8 text-yellow-400">@Get()</div>
|
||||
<div className="ml-8">getHello(): <span className="text-blue-400">string</span> {'{'}</div>
|
||||
<div className="ml-12 text-blue-400">return</div>
|
||||
<div className="ml-16 text-green-400">'Hello World!'</div>
|
||||
<div className="ml-8">{'}'}</div>
|
||||
<div className="ml-4">{'}'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="section-padding bg-nest-dark text-white"
|
||||
>
|
||||
<div className="container-custom text-center">
|
||||
<motion.h2
|
||||
{...fadeUpPreset(0.2, 0.8)}
|
||||
className="text-4xl md:text-5xl font-bold mb-6"
|
||||
>
|
||||
Live preview
|
||||
</motion.h2>
|
||||
<motion.p
|
||||
{...fadeUpPreset(0.3, 0.8)}
|
||||
className="text-xl text-gray-300 mb-12 max-w-2xl mx-auto"
|
||||
>
|
||||
See NestJS in action with our interactive examples and live coding environment.
|
||||
</motion.p>
|
||||
<motion.div
|
||||
{...fadeUpPreset(0.4, 0.8)}
|
||||
className="bg-black/50 rounded-lg p-8 max-w-4xl mx-auto"
|
||||
>
|
||||
<div className="text-left">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<div className="w-3 h-3 bg-red-500 rounded-full"></div>
|
||||
<div className="w-3 h-3 bg-yellow-500 rounded-full"></div>
|
||||
<div className="w-3 h-3 bg-green-500 rounded-full"></div>
|
||||
</div>
|
||||
<div className="font-mono text-sm text-gray-300">
|
||||
<div className="text-blue-400">import</div>
|
||||
<div className="ml-4">{'{ Controller, Get }'} <span className="text-blue-400">from</span> <span className="text-green-400">'@nestjs/common'</span>;</div>
|
||||
<div className="mt-4 text-yellow-400">@Controller()</div>
|
||||
<div className="text-blue-400">export class</div>
|
||||
<div className="ml-4">AppController {'{'}</div>
|
||||
<div className="ml-8 text-yellow-400">@Get()</div>
|
||||
<div className="ml-8">getHello(): <span className="text-blue-400">string</span> {'{'}</div>
|
||||
<div className="ml-12 text-blue-400">return</div>
|
||||
<div className="ml-16 text-green-400">'Hello World!'</div>
|
||||
<div className="ml-8">{'}'}</div>
|
||||
<div className="ml-4">{'}'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default LivePreview;
|
||||
120
src/components/SupportSection.js
Normal file
120
src/components/SupportSection.js
Normal file
@@ -0,0 +1,120 @@
|
||||
import React from 'react';
|
||||
import { motion, useReducedMotion } from 'framer-motion';
|
||||
|
||||
const fadeUpPreset = (delay = 0, duration = 1.2) => ({
|
||||
initial: { opacity: 0, y: 20 },
|
||||
whileInView: { opacity: 1, y: 0 },
|
||||
viewport: { once: true, amount: 0.2 },
|
||||
transition: { delay, duration, ease: "easeOut" }
|
||||
});
|
||||
|
||||
function SupportSection() {
|
||||
const shouldReduce = useReducedMotion();
|
||||
|
||||
const supportOptions = [
|
||||
{
|
||||
title: "PRINCIPAL SPONSORS",
|
||||
items: ["Valor Software", "Adyen", "Sanofi"]
|
||||
},
|
||||
{
|
||||
title: "GOLD SPONSORS",
|
||||
items: ["Trilon", "Amplication"]
|
||||
},
|
||||
{
|
||||
title: "SILVER SPONSORS",
|
||||
items: ["Nx", "Sentry", "JetBrains"]
|
||||
},
|
||||
{
|
||||
title: "SPONSORS / PARTNERS",
|
||||
items: ["Various Partners"]
|
||||
}
|
||||
];
|
||||
|
||||
if (shouldReduce) {
|
||||
return (
|
||||
<section className="section-padding bg-white">
|
||||
<div className="container-custom text-center">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
||||
Support us
|
||||
</h2>
|
||||
<p className="text-xl text-nest-gray mb-16 max-w-3xl mx-auto">
|
||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12">
|
||||
{supportOptions.map((option, index) => (
|
||||
<div key={index} className="text-center">
|
||||
<h3 className="font-bold text-sm text-nest-red mb-4">
|
||||
{option.title}
|
||||
</h3>
|
||||
<div className="space-y-2">
|
||||
{option.items.map((item, itemIndex) => (
|
||||
<div key={itemIndex} className="text-nest-gray text-sm">
|
||||
{item}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<button className="btn-primary">
|
||||
Become a sponsor
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
{...fadeUpPreset(0.1, 1.0)}
|
||||
className="section-padding bg-white"
|
||||
>
|
||||
<div className="container-custom text-center">
|
||||
<motion.h2
|
||||
{...fadeUpPreset(0.2, 0.8)}
|
||||
className="text-4xl md:text-5xl font-bold mb-6"
|
||||
>
|
||||
Support us
|
||||
</motion.h2>
|
||||
<motion.p
|
||||
{...fadeUpPreset(0.3, 0.8)}
|
||||
className="text-xl text-nest-gray mb-16 max-w-3xl mx-auto"
|
||||
>
|
||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.
|
||||
</motion.p>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12">
|
||||
{supportOptions.map((option, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
{...fadeUpPreset(0.4 + (index * 0.1), 0.6)}
|
||||
className="text-center"
|
||||
>
|
||||
<h3 className="font-bold text-sm text-nest-red mb-4">
|
||||
{option.title}
|
||||
</h3>
|
||||
<div className="space-y-2">
|
||||
{option.items.map((item, itemIndex) => (
|
||||
<div key={itemIndex} className="text-nest-gray text-sm">
|
||||
{item}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
{...fadeUpPreset(0.8, 0.6)}
|
||||
className="btn-primary"
|
||||
>
|
||||
Become a sponsor
|
||||
</motion.button>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default SupportSection;
|
||||
31
src/index.css
Normal file
31
src/index.css
Normal file
@@ -0,0 +1,31 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
@apply font-sans text-gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.btn-primary {
|
||||
@apply bg-nest-red text-white px-6 py-3 rounded-lg font-medium hover:bg-red-600 transition-colors duration-200;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply border border-white text-white px-6 py-3 rounded-lg font-medium hover:bg-white hover:text-gray-900 transition-colors duration-200;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
@apply bg-white p-8 rounded-lg shadow-sm hover:shadow-md transition-shadow duration-200;
|
||||
}
|
||||
|
||||
.section-padding {
|
||||
@apply py-16 md:py-24;
|
||||
}
|
||||
|
||||
.container-custom {
|
||||
@apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
|
||||
}
|
||||
}
|
||||
8
src/index.js
Normal file
8
src/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
const container = document.getElementById('root');
|
||||
const root = createRoot(container);
|
||||
root.render(<App />);
|
||||
Reference in New Issue
Block a user