From 460849262786d5993937e52581ff763b2cea142f Mon Sep 17 00:00:00 2001 From: vitaliimulika-dev Date: Fri, 16 Jan 2026 13:05:17 +0200 Subject: [PATCH] Initial commit --- .env.production | 1 + .gitea/workflows/build.yml | 62 ++ package.json | 41 + postcss.config.js | 6 + public/index.html | 1235 ++++++++++++++++++++++++++ src/App.js | 32 + src/components/CoursesSection.js | 39 + src/components/DeploySection.js | 56 ++ src/components/EnterpriseSection.js | 51 ++ src/components/EverythingSection.js | 103 +++ src/components/Features.js | 66 ++ src/components/Footer.js | 55 ++ src/components/Header.js | 54 ++ src/components/Hero.js | 53 ++ src/components/LivePreviewSection.js | 38 + src/components/NewsletterSection.js | 66 ++ src/components/SupportSection.js | 99 +++ src/index.css | 99 +++ src/index.js | 8 + tailwind.config.js | 23 + vercel.json | 5 + 21 files changed, 2192 insertions(+) create mode 100644 .env.production create mode 100644 .gitea/workflows/build.yml create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 public/index.html create mode 100644 src/App.js create mode 100644 src/components/CoursesSection.js create mode 100644 src/components/DeploySection.js create mode 100644 src/components/EnterpriseSection.js create mode 100644 src/components/EverythingSection.js create mode 100644 src/components/Features.js create mode 100644 src/components/Footer.js create mode 100644 src/components/Header.js create mode 100644 src/components/Hero.js create mode 100644 src/components/LivePreviewSection.js create mode 100644 src/components/NewsletterSection.js create mode 100644 src/components/SupportSection.js create mode 100644 src/index.css create mode 100644 src/index.js create mode 100644 tailwind.config.js create mode 100644 vercel.json diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..02269f0 --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +DISABLE_ESLINT_PLUGIN=true diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..8687ee0 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,62 @@ +name: Build + +on: + workflow_dispatch: + inputs: + branch: + description: 'Branch to build' + required: true + default: 'main' + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout branch + uses: actions/checkout@v3 + with: + ref: ${{ gitea.event.inputs.branch }} + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 24 + + - name: Install dependencies + run: | + set -euo pipefail + npm install --no-audit --silent 2>&1 | tee install.log + env: + NODE_OPTIONS: '--max-old-space-size=4096' + + - name: Build (react-scripts build) + env: + CI: 'false' + NODE_OPTIONS: '--max-old-space-size=4096' + run: | + set -euo pipefail + npm run build 2>&1 | tee build.log + timeout-minutes: 5 + + - name: Verify build folder exists + run: test -d build || (echo "No build folder. Check build logs above."; exit 1) + + - name: Upload logs on failure + if: failure() + uses: actions/upload-artifact@v3 + with: + name: build-logs + path: | + install.log + build.log + npm-debug.log* + if-no-files-found: ignore + + - name: Build completed + if: success() + run: echo "Build completed successfully" diff --git a/package.json b/package.json new file mode 100644 index 0000000..74276b0 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "nestjs-website", + "version": "0.1.0", + "private": true, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-scripts": "^5.0.1", + "lucide-react": "^0.400.0", + "framer-motion": "^11.0.0" + }, + "devDependencies": { + "tailwindcss": "^3.4.0", + "postcss": "^8.4.0", + "autoprefixer": "^10.4.0" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} \ No newline at end of file diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..96bb01e --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..f6cdf2f --- /dev/null +++ b/public/index.html @@ -0,0 +1,1235 @@ + + + + + + + + + NestJS - A progressive Node.js framework + + + +
+ + + + + \ No newline at end of file diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000..ce66d49 --- /dev/null +++ b/src/App.js @@ -0,0 +1,32 @@ +import React from 'react'; +import Header from './components/Header'; +import Hero from './components/Hero'; +import Features from './components/Features'; +import EverythingSection from './components/EverythingSection'; +import DeploySection from './components/DeploySection'; +import CoursesSection from './components/CoursesSection'; +import EnterpriseSection from './components/EnterpriseSection'; +import LivePreviewSection from './components/LivePreviewSection'; +import SupportSection from './components/SupportSection'; +import NewsletterSection from './components/NewsletterSection'; +import Footer from './components/Footer'; + +function App() { + return ( +
+
+ + + + + + + + + +
+
+ ); +} + +export default App; \ No newline at end of file diff --git a/src/components/CoursesSection.js b/src/components/CoursesSection.js new file mode 100644 index 0000000..48edcbb --- /dev/null +++ b/src/components/CoursesSection.js @@ -0,0 +1,39 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function CoursesSection() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + return ( +
+
+ +

+ Official NestJS Courses +

+

+ Learn everything you need to master NestJS and tackle modern backend applications at any scale. +

+ +
+
+
+ ); +} + +export default CoursesSection; \ No newline at end of file diff --git a/src/components/DeploySection.js b/src/components/DeploySection.js new file mode 100644 index 0000000..e675a80 --- /dev/null +++ b/src/components/DeploySection.js @@ -0,0 +1,56 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function DeploySection() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + return ( +
+
+
+ +

+ Deploy, mau! +

+

+ Provision and manage your infrastracture on AWS without the hassle and extra DevOps work. +

+ +
+ + +

+ Explore your graph +

+

+ Identify dependencies and connections between modules, and dive deep into the inner workings of your classes. +

+ +
+
+
+
+ ); +} + +export default DeploySection; \ No newline at end of file diff --git a/src/components/EnterpriseSection.js b/src/components/EnterpriseSection.js new file mode 100644 index 0000000..774814f --- /dev/null +++ b/src/components/EnterpriseSection.js @@ -0,0 +1,51 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function EnterpriseSection() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + return ( +
+
+ +
+
+
+ + The open source platform designed for the future. Build enterprise. + + + + A complete development kit for building scalable server-side apps. Contact us to find out more about expertise consulting, on-site enterprise support, trainings, and private sessions. + + + + Learn more about support offerings + +
+
+
+
+ ); +} + +export default EnterpriseSection; \ No newline at end of file diff --git a/src/components/EverythingSection.js b/src/components/EverythingSection.js new file mode 100644 index 0000000..d21654e --- /dev/null +++ b/src/components/EverythingSection.js @@ -0,0 +1,103 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function EverythingSection() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + const features = [ + { + icon: 'https://nestjs.com/puzzle.c9dfc495.svg', + title: 'MODULARITY', + description: 'Streamline upkeep by organizing applications into self-contained modules.' + }, + { + icon: 'https://nestjs.com/rocket.518dadfa.svg', + title: 'SCALABILITY', + description: 'Scale seamlessly with efficient, battle-tested components.' + }, + { + icon: 'https://nestjs.com/di.a0b12f44.svg', + title: 'DEPENDENCY INJECTION', + description: 'Elevate testability with a sophisticated dependency injection system.' + }, + { + icon: 'https://nestjs.com/type-safety.34453790.svg', + title: 'TYPE SAFETY', + description: 'Mitigate errors through the robust type safety features of TypeScript.' + }, + { + icon: 'https://nestjs.com/ecosystem.eaa69289.svg', + title: 'RICH ECOSYSTEM', + description: 'Explore a rich ecosystem offering versatile tools to craft solutions tailored to your needs.' + }, + { + icon: 'https://nestjs.com/chip.3b61cda8.svg', + title: 'ENTERPRISE-READY', + description: 'Trusted by thousands of leading companies and organizations worldwide.' + }, + { + icon: 'https://nestjs.com/microservices.e0074903.svg', + title: 'MICROSERVICES', + description: 'Create loosely coupled, independently deployable services for increased agility and scalability.' + }, + { + icon: 'https://nestjs.com/api.67807f71.svg', + title: 'WEB APPS', + description: 'Build REST APIs, GraphQL APIs, Queues, and real-time & event-driven applications in no time.' + } + ]; + + return ( +
+
+ +

+ Everything you need.. +

+

+ Build robust, powerful, and scalable server-side applications and stop reinventing the wheel. +

+
+ +
+ {features.map((feature, index) => ( + +
+ {feature.title} +
+

+ {feature.title} +

+

+ {feature.description} +

+
+ ))} +
+
+
+ ); +} + +export default EverythingSection; \ No newline at end of file diff --git a/src/components/Features.js b/src/components/Features.js new file mode 100644 index 0000000..1c6e8b1 --- /dev/null +++ b/src/components/Features.js @@ -0,0 +1,66 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function Features() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + const features = [ + { + icon: 'https://nestjs.com/3d.cfabe065.svg', + title: 'EXTENSIBLE', + description: 'Provides unparalleled flexibility through its meticulously crafted modular architecture.' + }, + { + icon: 'https://nestjs.com/magic-wand.ff01fe1d.svg', + title: 'VERSATILE', + description: 'Serves as a robust, elegant, and well-structured foundation for all kinds of server-side applications.' + }, + { + icon: 'https://nestjs.com/quality.d1d04ce8.svg', + title: 'PROGRESSIVE', + description: 'Introduces design patterns and well-established solutions to the Node.js landscape.' + } + ]; + + return ( +
+
+
+ {features.map((feature, index) => ( + +
+ {feature.title} +
+

+ {feature.title} +

+

+ {feature.description} +

+
+ ))} +
+
+
+ ); +} + +export default Features; \ No newline at end of file diff --git a/src/components/Footer.js b/src/components/Footer.js new file mode 100644 index 0000000..5732f5c --- /dev/null +++ b/src/components/Footer.js @@ -0,0 +1,55 @@ +import React from 'react'; +import { Github, ExternalLink } from 'lucide-react'; + +function Footer() { + return ( + + ); +} + +export default Footer; \ No newline at end of file diff --git a/src/components/Header.js b/src/components/Header.js new file mode 100644 index 0000000..44f1360 --- /dev/null +++ b/src/components/Header.js @@ -0,0 +1,54 @@ +import React from 'react'; +import { Github, ExternalLink, ChevronDown } from 'lucide-react'; + +function Header() { + return ( +
+
+
+
+ + NestJS - A progressive Node.js framework + +
+ + + +
+ + + + + + + + + +
+
+
+
+ ); +} + +export default Header; \ No newline at end of file diff --git a/src/components/Hero.js b/src/components/Hero.js new file mode 100644 index 0000000..3c80123 --- /dev/null +++ b/src/components/Hero.js @@ -0,0 +1,53 @@ +import React from 'react'; +import { Github } from 'lucide-react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function Hero() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + animate: { opacity: 1, y: 0 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + return ( +
+
+ +
+ + Hello, nest! + + + + A progressive Node.js framework for building efficient, reliable and scalable server-side applications. + + + + + + +
+
+ ); +} + +export default Hero; \ No newline at end of file diff --git a/src/components/LivePreviewSection.js b/src/components/LivePreviewSection.js new file mode 100644 index 0000000..3fdaf51 --- /dev/null +++ b/src/components/LivePreviewSection.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function LivePreviewSection() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + return ( +
+
+ + Live preview + + + + See how your application may potentially look like without leaving your personal browser. + +
+
+ ); +} + +export default LivePreviewSection; \ No newline at end of file diff --git a/src/components/NewsletterSection.js b/src/components/NewsletterSection.js new file mode 100644 index 0000000..92ce0b8 --- /dev/null +++ b/src/components/NewsletterSection.js @@ -0,0 +1,66 @@ +import React, { useState } from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function NewsletterSection() { + const [email, setEmail] = useState(''); + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + const handleSubmit = (e) => { + e.preventDefault(); + console.log('Newsletter signup:', email); + setEmail(''); + }; + + return ( +
+
+ + Join our Newsletter + + + + Subscribe to stay up to date with the latest Nest updates, features, and videos! + + + + setEmail(e.target.value)} + placeholder="Enter your email" + className="flex-1 px-4 py-3 rounded-full border border-accent bg-card text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary" + required + /> + + +
+
+ ); +} + +export default NewsletterSection; \ No newline at end of file diff --git a/src/components/SupportSection.js b/src/components/SupportSection.js new file mode 100644 index 0000000..dc94a00 --- /dev/null +++ b/src/components/SupportSection.js @@ -0,0 +1,99 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function SupportSection() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay, duration = 1.2) => { + if (shouldReduceMotion) return {}; + return { + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }; + }; + + const principalSponsors = [ + { src: 'https://nestjs.com/trilon.22c96544.svg', alt: 'Trilon', link: 'https://trilon.io/' }, + { src: 'https://nestjs.com/red-hat-logo.17d10010.svg', alt: 'Red Hat', link: 'https://www.redhat.com/' }, + { src: 'https://nestjs.com/jetbrains-logo.d24f46f1.svg', alt: 'Jetbrains', link: 'https://www.jetbrains.com/' } + ]; + + const goldSponsors = [ + { src: 'https://nestjs.com/movavi-logo.eee1bd94.svg', alt: 'Movavi', link: 'https://www.movavi.com/' }, + { src: 'https://nestjs.com/handsontable-logo.9006297e.svg', link: 'https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_homepage&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024' }, + { src: 'https://nestjs.com/arcjet-logo.79e2da28.svg', link: 'https://arcjet.com/?ref=nestjs' }, + { src: 'https://nestjs.com/crawljobs-logo.53b333f7.svg', link: 'https://www.crawljobs.com/' } + ]; + + const silverSponsors = [ + { src: 'https://nestjs.com/netlify-logo.9322c2d1.svg', link: 'https://www.netlify.com/' }, + { src: 'https://nestjs.com/swingdev-logo.168e0bec.svg', link: 'https://www.swingdev.io/' }, + { src: 'https://nestjs.com/route4me-logo.d07e8982.svg', link: 'https://www.route4me.com/' } + ]; + + return ( +
+
+ + Support us + + + + Nest is an MIT-licensed open-source project. Hence, it grows thanks to the sponsors and support by the amazing backers. Please, consider supporting us! + + +
+ +

PRINCIPAL SPONSORS

+
+ {principalSponsors.map((sponsor, index) => ( + + {sponsor.alt} + + ))} +
+
+ + +

GOLD SPONSORS

+
+ {goldSponsors.map((sponsor, index) => ( + + {sponsor.alt + + ))} +
+
+ + +

SILVER SPONSORS

+
+ {silverSponsors.map((sponsor, index) => ( + + {sponsor.alt + + ))} +
+
+
+ + + Become a sponsor / backer + +
+
+ ); +} + +export default SupportSection; \ No newline at end of file diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..cc9b1c7 --- /dev/null +++ b/src/index.css @@ -0,0 +1,99 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --background: #0a0a0a; + --card: #1a1a1a; + --foreground: #ffffffe6; + --primary-cta: #e63946; + --secondary-cta: #1a1a1a; + --accent: #737373; + --background-accent: #737373; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background-color: var(--background); + color: var(--foreground); +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + +.bg-background { + background-color: var(--background); +} + +.bg-card { + background-color: var(--card); +} + +.bg-primary { + background-color: var(--primary-cta); +} + +.bg-secondary { + background-color: var(--secondary-cta); +} + +.bg-accent { + background-color: var(--accent); +} + +.text-foreground { + color: var(--foreground); +} + +.text-primary { + color: var(--primary-cta); +} + +.text-accent { + color: var(--accent); +} + +.border-accent { + border-color: var(--accent); +} + +.hero-bg { + background-image: url('https://nestjs.com/header.e5c9eff6.webp'); + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +.support-bg { + background-image: url('https://nestjs.com/support.1356a495.png'); + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + +.btn-primary { + @apply bg-primary text-white px-6 py-3 rounded-full font-medium hover:opacity-90 transition-opacity; +} + +.btn-secondary { + @apply bg-transparent border border-accent text-foreground px-6 py-3 rounded-full font-medium hover:bg-accent hover:text-background transition-colors; +} + +.feature-card { + @apply bg-card p-6 rounded-lg text-center; +} + +.sponsor-logo { + @apply opacity-60 hover:opacity-100 transition-opacity; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..1ede065 --- /dev/null +++ b/src/index.js @@ -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(); \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..df8cce3 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,23 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./src/**/*.{js,jsx,ts,tsx}", + ], + theme: { + extend: { + colors: { + background: 'var(--background)', + card: 'var(--card)', + foreground: 'var(--foreground)', + primary: 'var(--primary-cta)', + secondary: 'var(--secondary-cta)', + accent: 'var(--accent)', + 'background-accent': 'var(--background-accent)', + }, + fontFamily: { + sans: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'sans-serif'], + }, + }, + }, + plugins: [], +} \ No newline at end of file diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..760984a --- /dev/null +++ b/vercel.json @@ -0,0 +1,5 @@ +{ + "installCommand": "npm install", + "buildCommand": "CI=false npm run build", + "outputDirectory": "build" +} \ No newline at end of file