commit d5432a0a4c197bb9e7f1b6ce870722a97dff1677 Author: vitaliimulika-dev Date: Fri Jan 23 12:19:46 2026 +0200 Initial commit 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..58057f1 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "react-dev-clone", + "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..90d08b4 --- /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..1f14573 --- /dev/null +++ b/public/index.html @@ -0,0 +1,1232 @@ + + + + + + + + + React + + + +
+ + + + + \ No newline at end of file diff --git a/src/App.js b/src/App.js new file mode 100644 index 0000000..be233b6 --- /dev/null +++ b/src/App.js @@ -0,0 +1,28 @@ +import React from 'react'; +import Header from './components/Header'; +import Hero from './components/Hero'; +import Features from './components/Features'; +import CodeExamples from './components/CodeExamples'; +import Platforms from './components/Platforms'; +import News from './components/News'; +import Community from './components/Community'; +import Footer from './components/Footer'; + +function App() { + return ( +
+
+
+ + + + + + +
+
+
+ ); +} + +export default App; \ No newline at end of file diff --git a/src/components/CodeExamples.js b/src/components/CodeExamples.js new file mode 100644 index 0000000..b6470ff --- /dev/null +++ b/src/components/CodeExamples.js @@ -0,0 +1,108 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function CodeExamples() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay = 0, duration = 0.8) => ({ + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }); + + const frameworkExample = { + title: "Go full-stack with a framework", + description: "React is a library. It lets you put components together, but it doesn't prescribe how to do routing and data fetching. To build an entire app with React, we recommend a full-stack React framework like Next.js or React Router.", + code: `import { db } from './database.js'; +import { Suspense } from 'react'; + +async function ConferencePage({ slug }) { + const conf = await db.Confs.find({ slug }); + return ( + + }> + + + + ); +} + +async function Talks({ confId }) { + const talks = await db.Talks.findAll({ confId }); + const videos = talks.map(talk => talk.video); + return ; +}`, + note: "React is also an architecture. Frameworks that implement it let you fetch data in asynchronous components that run on the server or even during the build. Read data from a file or a database, and pass it down to your interactive components.", + cta: "Get started with a framework" + }; + + if (shouldReduceMotion) { + return ( +
+
+
+
+

+ {frameworkExample.title} +

+

+ {frameworkExample.description} +

+

+ {frameworkExample.note} +

+ +
+
+
+
{frameworkExample.code}
+
+
+ example.com/confs/react-conf-2021 +
+
+
+
+
+ ); + } + + return ( + +
+
+ +

+ {frameworkExample.title} +

+

+ {frameworkExample.description} +

+

+ {frameworkExample.note} +

+ +
+ +
+
{frameworkExample.code}
+
+
+ example.com/confs/react-conf-2021 +
+
+
+
+
+ ); +} + +export default CodeExamples; \ No newline at end of file diff --git a/src/components/Community.js b/src/components/Community.js new file mode 100644 index 0000000..97ed9c8 --- /dev/null +++ b/src/components/Community.js @@ -0,0 +1,135 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; +import { Users, Heart } from 'lucide-react'; + +function Community() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay = 0, duration = 0.8) => ({ + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }); + + const communityImages = [ + "https://react.dev/images/home/conf2021/andrew.jpg", + "https://react.dev/images/home/conf2021/lauren.jpg", + "https://react.dev/images/home/conf2021/juan.jpg", + "https://react.dev/images/home/conf2021/rick.jpg" + ]; + + if (shouldReduceMotion) { + return ( +
+
+
+
+ +

+ Join a community of millions +

+
+

+ You're not alone. Two million developers from all over the world visit the React docs every month. React is something that people and teams can agree on. +

+
+ +
+ {communityImages.map((image, index) => ( +
+ {`Community +
+ ))} +
+ +
+

+ This is why React is more than a library, an architecture, or even an ecosystem. React is a community. It's a place where you can ask for help, find opportunities, and meet new friends. You will meet both developers and designers, beginners and experts, researchers and artists, teachers and students. Our backgrounds may be very different, but React lets us all create user interfaces together. +

+ +
+
+
+ +
+
+

+ Welcome to the React community +

+ +
+
+
+
+ ); + } + + return ( + +
+ +
+ +

+ Join a community of millions +

+
+

+ You're not alone. Two million developers from all over the world visit the React docs every month. React is something that people and teams can agree on. +

+
+ + + {communityImages.map((image, index) => ( + + {`Community + + ))} + + + +

+ This is why React is more than a library, an architecture, or even an ecosystem. React is a community. It's a place where you can ask for help, find opportunities, and meet new friends. You will meet both developers and designers, beginners and experts, researchers and artists, teachers and students. Our backgrounds may be very different, but React lets us all create user interfaces together. +

+ + +
+
+ +
+
+

+ Welcome to the React community +

+ +
+
+
+
+ ); +} + +export default Community; \ No newline at end of file diff --git a/src/components/Features.js b/src/components/Features.js new file mode 100644 index 0000000..1b1db35 --- /dev/null +++ b/src/components/Features.js @@ -0,0 +1,156 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function Features() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay = 0, duration = 0.8) => ({ + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }); + + const features = [ + { + title: "Create user interfaces from components", + description: "React lets you build user interfaces out of individual pieces called components. Create your own React components like Thumbnail, LikeButton, and Video. Then combine them into entire screens, pages, and apps.", + code: `function Video({ video }) { + return ( +
+ + +

{video.title}

+

{video.description}

+
+ +
+ ); +}`, + note: "Whether you work on your own or with thousands of other developers, using React feels the same. It is designed to let you seamlessly combine components written by independent people, teams, and organizations." + }, + { + title: "Write components with code and markup", + description: "React components are JavaScript functions. Want to show some content conditionally? Use an if statement. Displaying a list? Try array map(). Learning React is learning programming.", + code: `function VideoList({ videos, emptyHeading }) { + const count = videos.length; + let heading = emptyHeading; + if (count > 0) { + const noun = count > 1 ? 'Videos' : 'Video'; + heading = count + ' ' + noun; + } + return ( +
+

{heading}

+ {videos.map(video => +
+ ); +}`, + note: "This markup syntax is called JSX. It is a JavaScript syntax extension popularized by React. Putting JSX markup close to related rendering logic makes React components easy to create, maintain, and delete." + }, + { + title: "Add interactivity wherever you need it", + description: "React components receive data and return what should appear on the screen. You can pass them new data in response to an interaction, like when the user types into an input. React will then update the screen to match the new data.", + code: `import { useState } from 'react'; + +function SearchableVideoList({ videos }) { + const [searchText, setSearchText] = useState(''); + const foundVideos = filterVideos(videos, searchText); + return ( + <> + setSearchText(newText)} /> + + + ); +}`, + note: "You don't have to build your whole page in React. Add React to your existing HTML page, and render interactive React components anywhere on it.", + cta: "Add React to your page" + } + ]; + + if (shouldReduceMotion) { + return ( +
+
+ {features.map((feature, index) => ( +
+
+
+

+ {feature.title} +

+

+ {feature.description} +

+ {feature.note && ( +

+ {feature.note} +

+ )} + {feature.cta && ( + + )} +
+
+
+
{feature.code}
+
+
+
+
+ ))} +
+
+ ); + } + + return ( +
+
+ {features.map((feature, index) => ( + +
+
+

+ {feature.title} +

+

+ {feature.description} +

+ {feature.note && ( +

+ {feature.note} +

+ )} + {feature.cta && ( + + )} +
+
+
+
{feature.code}
+
+
+
+
+ ))} +
+
+ ); +} + +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..af4d6d9 --- /dev/null +++ b/src/components/Footer.js @@ -0,0 +1,126 @@ +import React from 'react'; +import { Facebook, Twitter, Github } from 'lucide-react'; + +function Footer() { + const footerSections = [ + { + title: "Learn React", + links: [ + "Quick Start", + "Installation", + "Describing the UI", + "Adding Interactivity", + "Managing State", + "Escape Hatches" + ] + }, + { + title: "API Reference", + links: [ + "React APIs", + "React DOM APIs" + ] + }, + { + title: "Community", + links: [ + "Code of Conduct", + "Meet the Team", + "Docs Contributors", + "Acknowledgements" + ] + }, + { + title: "More", + links: [ + "Blog", + "React Native", + "Privacy", + "Terms" + ] + } + ]; + + return ( +
+
+
+ {/* Logo and Meta */} +
+
+
+
+
+
+
+
+
+ React +
+
+
+ Meta Open Source +
+

+ Copyright © Meta Platforms, Inc +

+
+ logo by @sawaratsuki1004 + uwu? +
+
+
+ + {/* Footer Links */} + {footerSections.map((section, index) => ( +
+

{section.title}

+
    + {section.links.map((link, linkIndex) => ( +
  • + + {link} + +
  • + ))} +
+
+ ))} +
+ + {/* Social Links */} +
+
+
+ + + +
+
+ Made with + + by the React team +
+
+
+
+
+ ); +} + +function Heart({ className }) { + 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..0f0aafe --- /dev/null +++ b/src/components/Header.js @@ -0,0 +1,84 @@ +import React, { useState } from 'react'; +import { Search, Menu, X, Github } from 'lucide-react'; + +function Header() { + const [isMenuOpen, setIsMenuOpen] = useState(false); + + return ( +
+
+
+ {/* Logo */} +
+
+
+
+
+
+
+
+
+ React + v19.2 +
+
+ + {/* Search */} +
+
+ + +
+ Ctrl + K +
+
+
+ + {/* Navigation */} + + + {/* Mobile menu button */} + +
+
+ + {/* Mobile menu */} + {isMenuOpen && ( +
+
+
+ + +
+ Learn + Reference + Community + Blog +
+
+ )} +
+ ); +} + +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..a1bfd79 --- /dev/null +++ b/src/components/Hero.js @@ -0,0 +1,71 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; + +function Hero() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay = 0, duration = 0.8) => ({ + initial: { opacity: 0, y: 20 }, + animate: { opacity: 1, y: 0 }, + transition: { delay, duration, ease: "easeOut" } + }); + + if (shouldReduceMotion) { + return ( +
+
+
+
+
+
+
+
+
+
+

React

+

The library for web and native user interfaces

+
+ + +
+
+
+
+ ); + } + + return ( + +
+ +
+
+
+
+
+
+
+

React

+

The library for web and native user interfaces

+
+ + +
+
+
+
+ ); +} + +export default Hero; \ No newline at end of file diff --git a/src/components/News.js b/src/components/News.js new file mode 100644 index 0000000..0025115 --- /dev/null +++ b/src/components/News.js @@ -0,0 +1,134 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; +import { Calendar, TrendingUp } from 'lucide-react'; + +function News() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay = 0, duration = 0.8) => ({ + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }); + + const newsItems = [ + { + title: "Additional Vulnerabilities in RSC", + date: "December 11, 2025" + }, + { + title: "Vulnerability in React Server Components", + date: "December 3, 2025" + }, + { + title: "React Conf 2025 Recap", + date: "October 16, 2025" + }, + { + title: "React Compiler v1.0", + date: "October 7, 2025" + } + ]; + + if (shouldReduceMotion) { + return ( +
+
+
+ {/* Upgrade Section */} +
+
+ +

+ Upgrade when the future is ready +

+
+

+ React approaches changes with care. Every React commit is tested on business-critical surfaces with over a billion users. Over 100,000 React components at Meta help validate every migration strategy. +

+

+ The React team is always researching how to improve React. Some research takes years to pay off. React has a high bar for taking a research idea into production. Only proven approaches become a part of React. +

+ +
+ + {/* News Section */} +
+
+ +

LATEST REACT NEWS

+
+
+ {newsItems.map((item, index) => ( +
+

+ {item.title} +

+

{item.date}

+
+ ))} +
+
+
+
+
+ ); + } + + return ( + +
+
+ {/* Upgrade Section */} + +
+ +

+ Upgrade when the future is ready +

+
+

+ React approaches changes with care. Every React commit is tested on business-critical surfaces with over a billion users. Over 100,000 React components at Meta help validate every migration strategy. +

+

+ The React team is always researching how to improve React. Some research takes years to pay off. React has a high bar for taking a research idea into production. Only proven approaches become a part of React. +

+ +
+ + {/* News Section */} + +
+ +

LATEST REACT NEWS

+
+
+ {newsItems.map((item, index) => ( + +

+ {item.title} +

+

{item.date}

+
+ ))} +
+
+
+
+
+ ); +} + +export default News; \ No newline at end of file diff --git a/src/components/Platforms.js b/src/components/Platforms.js new file mode 100644 index 0000000..31f351e --- /dev/null +++ b/src/components/Platforms.js @@ -0,0 +1,136 @@ +import React from 'react'; +import { motion, useReducedMotion } from 'framer-motion'; +import { Globe, Phone } from 'lucide-react'; + +function Platforms() { + const shouldReduceMotion = useReducedMotion(); + + const fadeUpPreset = (delay = 0, duration = 0.8) => ({ + initial: { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, amount: 0.2 }, + transition: { delay, duration, ease: "easeOut" } + }); + + const platforms = [ + { + icon: Globe, + title: "Stay true to the web", + description: "People expect web app pages to load fast. On the server, React lets you start streaming HTML while you're still fetching data, progressively filling in the remaining content before any JavaScript code loads. On the client, React can use standard web APIs to keep your UI responsive even in the middle of rendering.", + image: "https://react.dev/images/home/videos/documentary.webp" + }, + { + icon: Phone, + title: "Go truly native", + description: "People expect native apps to look and feel like their platform. React Native and Expo let you build apps in React for Android, iOS, and more. They look and feel native because their UIs are truly native. It's not a web view—your React components render real Android and iOS views provided by the platform.", + image: "https://react.dev/images/home/videos/rn.jpg" + } + ]; + + if (shouldReduceMotion) { + return ( +
+
+
+

+ Use the best from every platform +

+

+ People love web and native apps for different reasons. React lets you build both web apps and native apps using the same skills. It leans upon each platform's unique strengths to let your interfaces feel just right on every platform. +

+
+ +
+ {platforms.map((platform, index) => { + const IconComponent = platform.icon; + return ( +
+
+ {platform.title} +
+
+
+ +

{platform.title}

+
+

{platform.description}

+
+
+ ); + })} +
+ +
+

+ With React, you can be a web and a native developer. Your team can ship to many platforms without sacrificing the user experience. Your organization can bridge the platform silos, and form teams that own entire features end-to-end. +

+ +
+
+
+ ); + } + + return ( + +
+ +

+ Use the best from every platform +

+

+ People love web and native apps for different reasons. React lets you build both web apps and native apps using the same skills. It leans upon each platform's unique strengths to let your interfaces feel just right on every platform. +

+
+ +
+ {platforms.map((platform, index) => { + const IconComponent = platform.icon; + return ( + +
+ {platform.title} +
+
+
+ +

{platform.title}

+
+

{platform.description}

+
+
+ ); + })} +
+ + +

+ With React, you can be a web and a native developer. Your team can ship to many platforms without sacrificing the user experience. Your organization can bridge the platform silos, and form teams that own entire features end-to-end. +

+ +
+
+
+ ); +} + +export default Platforms; \ No newline at end of file diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..8d3f804 --- /dev/null +++ b/src/index.css @@ -0,0 +1,62 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + html { + scroll-behavior: smooth; + } + + body { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + line-height: 1.6; + color: #1f2937; + } +} + +@layer components { + .code-block { + @apply bg-gray-900 text-gray-100 p-6 rounded-lg font-mono text-sm leading-relaxed overflow-x-auto; + } + + .code-line { + @apply block; + } + + .code-comment { + @apply text-gray-400; + } + + .code-keyword { + @apply text-purple-400; + } + + .code-string { + @apply text-green-400; + } + + .code-function { + @apply text-blue-400; + } + + .code-variable { + @apply text-yellow-400; + } + + .gradient-bg { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + } + + .react-logo { + animation: spin 20s linear infinite; + } + + @keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } +} \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..0881df3 --- /dev/null +++ b/src/index.js @@ -0,0 +1,13 @@ +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..3e151bb --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,27 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./src/**/*.{js,jsx,ts,tsx}", + "./public/index.html" + ], + theme: { + extend: { + colors: { + 'react-blue': '#087ea4', + 'react-light-blue': '#58c4dc', + 'react-dark': '#23272f', + 'react-gray': '#6b7280', + 'react-light-gray': '#f3f4f6', + 'react-border': '#e5e7eb' + }, + fontFamily: { + 'sans': ['system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'] + }, + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'meta-gradient': 'url("https://react.dev/images/meta-gradient.png")' + } + } + }, + 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