inital
This commit is contained in:
commit
424068648a
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
12
craco.config.js
Normal file
12
craco.config.js
Normal file
@ -0,0 +1,12 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
style: {
|
||||
postcss: {
|
||||
plugins: [
|
||||
require('tailwindcss'),
|
||||
require('autoprefixer'),
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
17
index.html
Normal file
17
index.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NebulaOS - The Future of Android</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
|
||||
<script type="text/babel" src="src/App.js"></script>
|
||||
</body>
|
||||
</html>
|
26910
package-lock.json
generated
Normal file
26910
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
37
package.json
Normal file
37
package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "nebulaos-site",
|
||||
"version": "1.0.0",
|
||||
"description": "Website for NebulaOS Android operating system",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"start": "react-scripts --openssl-legacy-provider start",
|
||||
"build": "react-scripts --openssl-legacy-provider build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"dependencies": {
|
||||
"framer-motion": "^4.1.17",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-icons": "^4.2.0",
|
||||
"react-router-dom": "^6.26.2",
|
||||
"react-scroll": "^1.9.0",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"react-scripts": "4.0.3"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('tailwindcss'),
|
||||
require('autoprefixer'),
|
||||
]
|
||||
}
|
27
public/index.html
Normal file
27
public/index.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="NebulaOS - The Future of Android"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<title>NebulaOS - The Future of Android</title>
|
||||
<script>
|
||||
window.process = {
|
||||
env: {
|
||||
NODE_ENV: 'development'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
38
src/App.js
Normal file
38
src/App.js
Normal file
@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
|
||||
import { motion } from 'framer-motion';
|
||||
import Header from './components/Header';
|
||||
import Hero from './components/Hero';
|
||||
import Features from './components/Features';
|
||||
import Footer from './components/Footer';
|
||||
import Download from './pages/Download';
|
||||
import Donate from './pages/Donate'; // Renamed from Support
|
||||
import styles from './App.module.css';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Router>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className={styles.app}
|
||||
>
|
||||
<Header />
|
||||
<Routes>
|
||||
<Route path="/" element={
|
||||
<main className={styles.main}>
|
||||
<Hero />
|
||||
<Features />
|
||||
</main>
|
||||
} />
|
||||
<Route path="/download" element={<Download />} />
|
||||
<Route path="/donate" element={<Donate />} /> {/* Changed to Donate */}
|
||||
</Routes>
|
||||
<Footer />
|
||||
</motion.div>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
9
src/App.module.css
Normal file
9
src/App.module.css
Normal file
@ -0,0 +1,9 @@
|
||||
.app {
|
||||
min-height: 100vh;
|
||||
background-color: #1a202c;
|
||||
color: #f0f4f8;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 2rem 0;
|
||||
}
|
16
src/components/Download.js
Normal file
16
src/components/Download.js
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
function Download() {
|
||||
return (
|
||||
<section id="download" className="py-20 bg-gray-100">
|
||||
<div className="container mx-auto px-4 text-center">
|
||||
<h2 className="text-4xl font-bold mb-8">Download NebulaOS</h2>
|
||||
<p className="text-xl mb-8">Experience the next generation of Android on your device today.</p>
|
||||
<a href="#" className="bg-purple-700 text-white px-8 py-3 rounded-full font-semibold hover:bg-purple-800 transition duration-300">Download Now</a>
|
||||
<p className="mt-4 text-sm text-gray-600">Compatible with most Android devices</p>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Download;
|
65
src/components/Features.js
Normal file
65
src/components/Features.js
Normal file
@ -0,0 +1,65 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import styles from './Features.module.css';
|
||||
|
||||
const features = [
|
||||
{ title: 'Sleek Design', description: 'Modern and intuitive user interface' },
|
||||
{ title: 'Enhanced Performance', description: 'Optimized for speed and efficiency' },
|
||||
{ title: 'Advanced Security', description: 'Cutting-edge protection for your device' },
|
||||
{ title: 'Customization', description: 'Tailor your experience to your preferences' },
|
||||
];
|
||||
|
||||
function Features() {
|
||||
const starryBackgroundRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const starryBackground = starryBackgroundRef.current;
|
||||
const numberOfStars = 100;
|
||||
|
||||
for (let i = 0; i < numberOfStars; i++) {
|
||||
const star = document.createElement('div');
|
||||
star.className = styles.star;
|
||||
star.style.width = `${Math.random() * 3}px`;
|
||||
star.style.height = star.style.width;
|
||||
star.style.left = `${Math.random() * 100}%`;
|
||||
star.style.top = `${Math.random() * 100}%`;
|
||||
star.style.animationDelay = `${Math.random() * 4}s`;
|
||||
starryBackground.appendChild(star);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section id="features" className={styles.features}>
|
||||
<div ref={starryBackgroundRef} className={styles.starryBackground}></div>
|
||||
<div className={styles.floatingElement}></div>
|
||||
<div className={styles.floatingElement}></div>
|
||||
<div className={styles.floatingElement}></div>
|
||||
<div className={styles.container}>
|
||||
<motion.h2
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className={styles.title}
|
||||
>
|
||||
Key Features
|
||||
</motion.h2>
|
||||
<div className={styles.featureGrid}>
|
||||
{features.map((feature, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
className={styles.featureCard}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
>
|
||||
<h3>{feature.title}</h3>
|
||||
<p>{feature.description}</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Features;
|
112
src/components/Features.module.css
Normal file
112
src/components/Features.module.css
Normal file
@ -0,0 +1,112 @@
|
||||
.features {
|
||||
background: linear-gradient(135deg, rgba(26, 32, 44, 0.9) 0%, rgba(45, 55, 72, 0.9) 100%);
|
||||
padding: 2rem 0; /* Reduced padding */
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.starryBackground {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.star {
|
||||
position: absolute;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
opacity: 0.3;
|
||||
animation: twinkle 4s infinite ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
0%, 100% { opacity: 0.3; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
.floatingElement {
|
||||
position: absolute;
|
||||
background: linear-gradient(135deg, rgba(129, 230, 217, 0.2), rgba(79, 209, 197, 0.2));
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
box-shadow: 0 0 20px rgba(129, 230, 217, 0.3);
|
||||
}
|
||||
|
||||
.floatingElement:nth-child(2) {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
top: 20%;
|
||||
right: 10%;
|
||||
animation: float 12s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.floatingElement:nth-child(3) {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
bottom: 15%;
|
||||
left: 5%;
|
||||
animation: float 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.floatingElement:nth-child(4) {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
top: 40%;
|
||||
left: 15%;
|
||||
animation: float 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translate(0, 0) rotate(0deg); }
|
||||
25% { transform: translate(10px, -10px) rotate(5deg); }
|
||||
50% { transform: translate(0, -20px) rotate(0deg); }
|
||||
75% { transform: translate(-10px, -10px) rotate(-5deg); }
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2rem; /* Reduced font size */
|
||||
text-align: center;
|
||||
margin-bottom: 1.5rem; /* Reduced margin */
|
||||
color: #81e6d9;
|
||||
}
|
||||
|
||||
.featureGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); /* Reduced minmax width */
|
||||
gap: 1.5rem; /* Reduced gap */
|
||||
}
|
||||
|
||||
.featureCard {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 10px;
|
||||
padding: 1rem; /* Reduced padding */
|
||||
backdrop-filter: blur(10px);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.featureCard:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.featureCard h3 {
|
||||
font-size: 1.3rem; /* Reduced font size */
|
||||
margin-bottom: 0.5rem;
|
||||
color: #81e6d9;
|
||||
}
|
||||
|
||||
.featureCard p {
|
||||
font-size: 0.9rem; /* Reduced font size */
|
||||
color: #e2e8f0;
|
||||
}
|
39
src/components/Footer.js
Normal file
39
src/components/Footer.js
Normal file
@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
import styles from './Footer.module.css';
|
||||
|
||||
function Footer() {
|
||||
return (
|
||||
<footer className={styles.footer}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.section}>
|
||||
<h3>NebulaOS</h3>
|
||||
<p>Revolutionizing mobile experiences</p>
|
||||
</div>
|
||||
<div className={styles.section}>
|
||||
<h4>Resources</h4>
|
||||
<ul>
|
||||
<li><a href="#features">Features</a></li>
|
||||
<li><a href="#download">Download</a></li>
|
||||
<li><a href="#support">Support</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className={styles.section}>
|
||||
<h4>Connect</h4>
|
||||
<ul>
|
||||
<li><a href="#">Twitter</a></li>
|
||||
<li><a href="#">Facebook</a></li>
|
||||
<li><a href="#">Instagram</a></li>
|
||||
<li><a href="#">GitHub</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.copyright}>
|
||||
<p>© 2024 NebulaOS. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
export default Footer;
|
61
src/components/Footer.module.css
Normal file
61
src/components/Footer.module.css
Normal file
@ -0,0 +1,61 @@
|
||||
.footer {
|
||||
background-color: #2d3748;
|
||||
color: #e2e8f0;
|
||||
padding: 4rem 0 2rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.section {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.section h3 {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
color: #81e6d9;
|
||||
}
|
||||
|
||||
.section h4 {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 1rem;
|
||||
color: #81e6d9;
|
||||
}
|
||||
|
||||
.section ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.section li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.section a {
|
||||
color: #e2e8f0;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.section a:hover {
|
||||
color: #81e6d9;
|
||||
}
|
||||
|
||||
.copyright {
|
||||
text-align: center;
|
||||
margin-top: 2rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid #4a5568;
|
||||
}
|
28
src/components/Header.js
Normal file
28
src/components/Header.js
Normal file
@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Link } from 'react-router-dom';
|
||||
import styles from './Header.module.css';
|
||||
|
||||
function Header() {
|
||||
return (
|
||||
<motion.header
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className={styles.header}
|
||||
>
|
||||
<div className={styles.container}>
|
||||
<Link to="/" className={styles.logo}>NebulaOS</Link>
|
||||
<nav className={styles.nav}>
|
||||
<ul>
|
||||
<li><Link to="/#features" className={styles.navLink}>Features</Link></li>
|
||||
<li><Link to="/download" className={styles.navLink}>Download</Link></li>
|
||||
<li><Link to="/donate" className={styles.navLink}>Donate</Link></li> {/* Changed to Donate */}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</motion.header>
|
||||
);
|
||||
}
|
||||
|
||||
export default Header;
|
68
src/components/Header.module.css
Normal file
68
src/components/Header.module.css
Normal file
@ -0,0 +1,68 @@
|
||||
.header {
|
||||
background: linear-gradient(to right, rgba(74, 85, 104, 0.7), rgba(45, 55, 72, 0.7));
|
||||
color: white;
|
||||
padding: 1rem 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.8rem;
|
||||
font-weight: bold;
|
||||
background: linear-gradient(45deg, #81e6d9, #4fd1c5, #38b2ac);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
text-shadow: 0 0 10px rgba(129, 230, 217, 0.3);
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav li {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
.nav a, .navLink {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 9999px;
|
||||
background: linear-gradient(45deg, rgba(129, 230, 217, 0.1), rgba(79, 209, 197, 0.1));
|
||||
}
|
||||
|
||||
.nav a:hover, .navLink:hover {
|
||||
background: linear-gradient(45deg, rgba(129, 230, 217, 0.3), rgba(79, 209, 197, 0.3));
|
||||
color: #81e6d9;
|
||||
box-shadow: 0 0 15px rgba(129, 230, 217, 0.3);
|
||||
}
|
||||
|
||||
.themeToggle {
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
margin-left: 2rem;
|
||||
}
|
71
src/components/Hero.js
Normal file
71
src/components/Hero.js
Normal file
@ -0,0 +1,71 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Link } from 'react-router-dom';
|
||||
import styles from './Hero.module.css';
|
||||
|
||||
function Hero() {
|
||||
const starryBackgroundRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const starryBackground = starryBackgroundRef.current;
|
||||
const numberOfStars = 100;
|
||||
|
||||
for (let i = 0; i < numberOfStars; i++) {
|
||||
const star = document.createElement('div');
|
||||
star.className = styles.star;
|
||||
star.style.width = `${Math.random() * 3}px`;
|
||||
star.style.height = star.style.width;
|
||||
star.style.left = `${Math.random() * 100}%`;
|
||||
star.style.top = `${Math.random() * 100}%`;
|
||||
star.style.animationDelay = `${Math.random() * 4}s`;
|
||||
starryBackground.appendChild(star);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<motion.section
|
||||
initial={{ opacity: 0, y: 50 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className={styles.hero}
|
||||
>
|
||||
<div ref={starryBackgroundRef} className={styles.starryBackground}></div>
|
||||
<div className={styles.floatingElement}></div>
|
||||
<div className={styles.floatingElement}></div>
|
||||
<div className={styles.floatingElement}></div>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<motion.h2
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.2, duration: 0.5 }}
|
||||
className={styles.comingSoon}
|
||||
>
|
||||
Coming Soon
|
||||
</motion.h2>
|
||||
<motion.h1
|
||||
initial={{ scale: 0.5 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ type: 'spring', stiffness: 260, damping: 20 }}
|
||||
>
|
||||
NebulaOS
|
||||
</motion.h1>
|
||||
<motion.p
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.4, duration: 0.5 }}
|
||||
>
|
||||
Get ready for the future of Android with our sleek and powerful operating system.
|
||||
</motion.p>
|
||||
<motion.div className={styles.ctaContainer}>
|
||||
<Link to="/download" className={styles.cta}>
|
||||
Download Beta
|
||||
</Link>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.section>
|
||||
);
|
||||
}
|
||||
|
||||
export default Hero;
|
146
src/components/Hero.module.css
Normal file
146
src/components/Hero.module.css
Normal file
@ -0,0 +1,146 @@
|
||||
.hero {
|
||||
background: linear-gradient(135deg, rgba(26, 32, 44, 0.9) 0%, rgba(45, 55, 72, 0.9) 100%);
|
||||
color: white;
|
||||
padding: 2rem 0; /* Reduced padding */
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 60vh; /* Reduced height */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.starryBackground {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.star {
|
||||
position: absolute;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
opacity: 0.3;
|
||||
animation: twinkle 4s infinite ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
0%, 100% { opacity: 0.3; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
.floatingElement {
|
||||
position: absolute;
|
||||
background: linear-gradient(135deg, rgba(129, 230, 217, 0.2), rgba(79, 209, 197, 0.2));
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
box-shadow: 0 0 20px rgba(129, 230, 217, 0.3);
|
||||
}
|
||||
|
||||
.floatingElement:nth-child(1) {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
top: 10%;
|
||||
left: 10%;
|
||||
animation: float 12s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.floatingElement:nth-child(2) {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
top: 20%;
|
||||
right: 20%;
|
||||
animation: float 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.floatingElement:nth-child(3) {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
bottom: 15%;
|
||||
left: 15%;
|
||||
animation: float 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translate(0, 0) rotate(0deg); }
|
||||
25% { transform: translate(10px, -10px) rotate(5deg); }
|
||||
50% { transform: translate(0, -20px) rotate(0deg); }
|
||||
75% { transform: translate(-10px, -10px) rotate(-5deg); }
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
backdrop-filter: blur(10px);
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
|
||||
padding: 1.5rem; /* Reduced padding */
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.2);
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
transform: translateY(0); /* Remove vertical translation */
|
||||
}
|
||||
|
||||
.content h1 {
|
||||
font-size: 3.5rem; /* Reduced font size */
|
||||
font-weight: bold;
|
||||
margin-bottom: 1rem;
|
||||
background: linear-gradient(45deg, #ffffff, #81e6d9, #4fd1c5);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.comingSoon {
|
||||
font-size: 1.5rem; /* Reduced font size */
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.5rem;
|
||||
color: #81e6d9;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.content p {
|
||||
font-size: 1.1rem; /* Reduced font size */
|
||||
margin-bottom: 1.5rem; /* Reduced margin */
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.ctaContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1rem; /* Add gap between buttons */
|
||||
}
|
||||
|
||||
.cta {
|
||||
display: inline-block;
|
||||
background: linear-gradient(45deg, rgba(129, 230, 217, 0.8), rgba(79, 209, 197, 0.8));
|
||||
color: #2d3748;
|
||||
padding: 1rem 2rem; /* Adjust padding */
|
||||
border-radius: 9999px;
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
backdrop-filter: blur(5px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
|
||||
.cta:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 12px rgba(0,0,0,0.15);
|
||||
background: linear-gradient(45deg, rgba(129, 230, 217, 1), rgba(79, 209, 197, 1));
|
||||
}
|
19
src/index.css
Normal file
19
src/index.css
Normal file
@ -0,0 +1,19 @@
|
||||
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;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
}
|
14
src/index.js
Normal file
14
src/index.js
Normal file
@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
reportWebVitals();
|
45
src/pages/Donate.js
Normal file
45
src/pages/Donate.js
Normal file
@ -0,0 +1,45 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import styles from './Donate.module.css';
|
||||
|
||||
function Donate() {
|
||||
const starryBackgroundRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const starryBackground = starryBackgroundRef.current;
|
||||
const numberOfStars = 100;
|
||||
|
||||
for (let i = 0; i < numberOfStars; i++) {
|
||||
const star = document.createElement('div');
|
||||
star.className = styles.star;
|
||||
star.style.width = `${Math.random() * 3}px`;
|
||||
star.style.height = star.style.width;
|
||||
star.style.left = `${Math.random() * 100}%`;
|
||||
star.style.top = `${Math.random() * 100}%`;
|
||||
star.style.animationDelay = `${Math.random() * 4}s`;
|
||||
starryBackground.appendChild(star);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className={styles.donatePage}
|
||||
>
|
||||
<div ref={starryBackgroundRef} className={styles.starryBackground}></div>
|
||||
<div className={styles.container}>
|
||||
<h1 className={styles.title}>Donate to NebulaOS</h1>
|
||||
<p className={styles.description}>
|
||||
Your support helps us continue developing and improving NebulaOS.
|
||||
Thank you for considering a donation!
|
||||
</p>
|
||||
{/* Add donation options or links here */}
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Donate;
|
11
src/pages/Donate.module.css
Normal file
11
src/pages/Donate.module.css
Normal file
@ -0,0 +1,11 @@
|
||||
.donatePage {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: linear-gradient(135deg, rgba(26, 32, 44, 0.9) 0%, rgba(45, 55, 72, 0.9) 100%);
|
||||
color: white;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
48
src/pages/Download.js
Normal file
48
src/pages/Download.js
Normal file
@ -0,0 +1,48 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import styles from './Download.module.css';
|
||||
|
||||
function Download() {
|
||||
const starryBackgroundRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const starryBackground = starryBackgroundRef.current;
|
||||
const numberOfStars = 100;
|
||||
|
||||
for (let i = 0; i < numberOfStars; i++) {
|
||||
const star = document.createElement('div');
|
||||
star.className = styles.star;
|
||||
star.style.width = `${Math.random() * 3}px`;
|
||||
star.style.height = star.style.width;
|
||||
star.style.left = `${Math.random() * 100}%`;
|
||||
star.style.top = `${Math.random() * 100}%`;
|
||||
star.style.animationDelay = `${Math.random() * 4}s`;
|
||||
starryBackground.appendChild(star);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className={styles.downloadPage}
|
||||
>
|
||||
<div ref={starryBackgroundRef} className={styles.starryBackground}></div>
|
||||
<div className={`${styles.floatingElement} ${styles.floatingElement1}`}></div>
|
||||
<div className={`${styles.floatingElement} ${styles.floatingElement2}`}></div>
|
||||
<div className={`${styles.floatingElement} ${styles.floatingElement3}`}></div>
|
||||
<div className={styles.container}>
|
||||
<h1 className={styles.title}>NebulaOS Download</h1>
|
||||
<p className={styles.comingSoon}>Coming Soon</p>
|
||||
<p className={styles.description}>
|
||||
We're working hard to bring you the future of Android.
|
||||
Stay tuned for the release of NebulaOS!
|
||||
</p>
|
||||
<a href="/" className={styles.backButton}>Back to Home</a>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Download;
|
125
src/pages/Download.module.css
Normal file
125
src/pages/Download.module.css
Normal file
@ -0,0 +1,125 @@
|
||||
.downloadPage {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: linear-gradient(135deg, rgba(26, 32, 44, 0.9) 0%, rgba(45, 55, 72, 0.9) 100%);
|
||||
color: white;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.starryBackground {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.star {
|
||||
position: absolute;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
opacity: 0.3;
|
||||
animation: twinkle 4s infinite ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
0%, 100% { opacity: 0.3; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
max-width: 600px;
|
||||
backdrop-filter: blur(10px);
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.2);
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
background: linear-gradient(45deg, #ffffff, #81e6d9, #4fd1c5);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.comingSoon {
|
||||
font-size: 2.5rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 1rem;
|
||||
color: #81e6d9;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.backButton {
|
||||
display: inline-block;
|
||||
background: linear-gradient(45deg, rgba(129, 230, 217, 0.8), rgba(79, 209, 197, 0.8));
|
||||
color: #2d3748;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 9999px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.backButton:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 12px rgba(0,0,0,0.15);
|
||||
background: linear-gradient(45deg, rgba(129, 230, 217, 1), rgba(79, 209, 197, 1));
|
||||
}
|
||||
|
||||
.floatingElement {
|
||||
position: absolute;
|
||||
background: linear-gradient(135deg, rgba(129, 230, 217, 0.2), rgba(79, 209, 197, 0.2));
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
box-shadow: 0 0 20px rgba(129, 230, 217, 0.3);
|
||||
}
|
||||
|
||||
.floatingElement1 {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
top: 10%;
|
||||
left: 10%;
|
||||
animation: float 12s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.floatingElement2 {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
top: 20%;
|
||||
right: 20%;
|
||||
animation: float 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.floatingElement3 {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
bottom: 15%;
|
||||
left: 15%;
|
||||
animation: float 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translate(0, 0) rotate(0deg); }
|
||||
25% { transform: translate(10px, -10px) rotate(5deg); }
|
||||
50% { transform: translate(0, -20px) rotate(0deg); }
|
||||
75% { transform: translate(-10px, -10px) rotate(-5deg); }
|
||||
}
|
48
src/pages/Support.js
Normal file
48
src/pages/Support.js
Normal file
@ -0,0 +1,48 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import styles from './Support.module.css';
|
||||
|
||||
function Support() {
|
||||
const starryBackgroundRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const starryBackground = starryBackgroundRef.current;
|
||||
const numberOfStars = 100;
|
||||
|
||||
for (let i = 0; i < numberOfStars; i++) {
|
||||
const star = document.createElement('div');
|
||||
star.className = styles.star;
|
||||
star.style.width = `${Math.random() * 3}px`;
|
||||
star.style.height = star.style.width;
|
||||
star.style.left = `${Math.random() * 100}%`;
|
||||
star.style.top = `${Math.random() * 100}%`;
|
||||
star.style.animationDelay = `${Math.random() * 4}s`;
|
||||
starryBackground.appendChild(star);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className={styles.supportPage}
|
||||
>
|
||||
<div ref={starryBackgroundRef} className={styles.starryBackground}></div>
|
||||
<div className={`${styles.floatingElement} ${styles.floatingElement1}`}></div>
|
||||
<div className={`${styles.floatingElement} ${styles.floatingElement2}`}></div>
|
||||
<div className={`${styles.floatingElement} ${styles.floatingElement3}`}></div>
|
||||
<div className={styles.container}>
|
||||
<h1 className={styles.title}>NebulaOS Support</h1>
|
||||
<p className={styles.comingSoon}>Coming Soon</p>
|
||||
<p className={styles.description}>
|
||||
We're working on building a comprehensive support system for NebulaOS.
|
||||
Stay tuned for updates on how you can get help and contribute to our project!
|
||||
</p>
|
||||
<a href="/" className={styles.backButton}>Back to Home</a>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Support;
|
125
src/pages/Support.module.css
Normal file
125
src/pages/Support.module.css
Normal file
@ -0,0 +1,125 @@
|
||||
.supportPage {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: linear-gradient(135deg, rgba(26, 32, 44, 0.9) 0%, rgba(45, 55, 72, 0.9) 100%);
|
||||
color: white;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.starryBackground {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.star {
|
||||
position: absolute;
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
opacity: 0.3;
|
||||
animation: twinkle 4s infinite ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
0%, 100% { opacity: 0.3; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
max-width: 600px;
|
||||
backdrop-filter: blur(10px);
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.2);
|
||||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
background: linear-gradient(45deg, #ffffff, #81e6d9, #4fd1c5);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.comingSoon {
|
||||
font-size: 2.5rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 1rem;
|
||||
color: #81e6d9;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.backButton {
|
||||
display: inline-block;
|
||||
background: linear-gradient(45deg, rgba(129, 230, 217, 0.8), rgba(79, 209, 197, 0.8));
|
||||
color: #2d3748;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 9999px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.backButton:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 12px rgba(0,0,0,0.15);
|
||||
background: linear-gradient(45deg, rgba(129, 230, 217, 1), rgba(79, 209, 197, 1));
|
||||
}
|
||||
|
||||
.floatingElement {
|
||||
position: absolute;
|
||||
background: linear-gradient(135deg, rgba(129, 230, 217, 0.2), rgba(79, 209, 197, 0.2));
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
box-shadow: 0 0 20px rgba(129, 230, 217, 0.3);
|
||||
}
|
||||
|
||||
.floatingElement1 {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
top: 10%;
|
||||
left: 10%;
|
||||
animation: float 12s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.floatingElement2 {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
top: 20%;
|
||||
right: 20%;
|
||||
animation: float 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.floatingElement3 {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
bottom: 15%;
|
||||
left: 15%;
|
||||
animation: float 10s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translate(0, 0) rotate(0deg); }
|
||||
25% { transform: translate(10px, -10px) rotate(5deg); }
|
||||
50% { transform: translate(0, -20px) rotate(0deg); }
|
||||
75% { transform: translate(-10px, -10px) rotate(-5deg); }
|
||||
}
|
13
src/reportWebVitals.js
Normal file
13
src/reportWebVitals.js
Normal file
@ -0,0 +1,13 @@
|
||||
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
|
||||
|
||||
const reportWebVitals = (onPerfEntry) => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
11
tailwind.config.js
Normal file
11
tailwind.config.js
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
|
||||
darkMode: 'class',
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
variants: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
Loading…
Reference in New Issue
Block a user