diff --git a/.env b/.env
index 7e40b56..7ee0421 100644
--- a/.env
+++ b/.env
@@ -12,6 +12,13 @@ TRANCO_USERNAME=''
TRANCO_API_KEY=''
CLOUDMERSIVE_API_KEY=''
+GOOGLE_CLOUD_API_KEY='AIzaSyB4bvds3nkHhw29X5_xX549LULaRYm_2iU'
+TORRENT_IP_API_KEY='385915166ab8461fbec188995e256dcf'
+REACT_APP_SHODAN_API_KEY='WB6B7tRAskjlmpVUrYfnU1CVGCIpUs1t'
+REACT_APP_WHO_API_KEY='0d49be5b3417cd42bd60712b139c730d'
+SECURITY_TRAILS_API_KEY='cakw8TzsKJisdQX1QBd1ejpHm04SQa3F'
+BUILT_WITH_API_KEY='6f6e1906-0c2a-4406-9d10-d7b5f2b21f25'
+
# API Keys for external services (frontend)
REACT_APP_SHODAN_API_KEY=''
REACT_APP_WHO_API_KEY=''
@@ -24,3 +31,4 @@ REACT_APP_WHO_API_KEY=''
# API_CORS_ORIGIN='*' # Enable CORS, by setting your allowed hostname(s) here
# API_ENABLE_RATE_LIMIT='true' # Enable rate limiting for the API
# REACT_APP_API_ENDPOINT='/api' # The endpoint for the API (can be local or remote)
+# ENABLE_ANALYTICS='false' # Enable Plausible hit counter for the frontend
diff --git a/astro.config.mjs b/astro.config.mjs
index 4097853..e33b157 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -1,7 +1,7 @@
import { defineConfig } from 'astro/config';
// Integrations
-// import svelte from '@astrojs/svelte';
+import svelte from '@astrojs/svelte';
import react from "@astrojs/react";
import partytown from '@astrojs/partytown';
import sitemap from '@astrojs/sitemap';
@@ -35,7 +35,7 @@ const base = unwrapEnvVar('BASE_URL', '/');
const isBossServer = unwrapEnvVar('BOSS_SERVER', false);
// Initialize Astro integrations
-const integrations = [react(), partytown(), sitemap()];
+const integrations = [svelte(), react(), partytown(), sitemap()];
// Set the appropriate adapter, based on the deploy target
function getAdapter(target) {
diff --git a/package.json b/package.json
index 1dbe809..f6edcda 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-rate-limit": "^7.2.0",
+ "framer-motion": "^11.2.6",
"got": "^14.2.1",
"pm2": "^5.3.1",
"psl": "^1.9.0",
@@ -42,6 +43,7 @@
"react-simple-maps": "^3.0.0",
"react-toastify": "^10.0.5",
"recharts": "^2.12.6",
+ "svelte": "^4.2.17",
"traceroute": "^1.0.0",
"typescript": "^5.4.5",
"unzipper": "^0.11.5",
diff --git a/src/components/HomeBackground.tsx b/src/components/HomeBackground.tsx
new file mode 100644
index 0000000..d1a2b8a
--- /dev/null
+++ b/src/components/HomeBackground.tsx
@@ -0,0 +1,119 @@
+import React, { useState, useEffect } from 'react';
+import { motion } from 'framer-motion';
+import styled from '@emotion/styled';
+
+const dotSpacing = 32;
+
+const Meteor = styled(motion.div)`
+ position: absolute;
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background-color: #9fef00;
+ box-shadow: 0 0 15px 3px #9fef00;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: -100px;
+ left: 0;
+ width: 2px;
+ height: 100px;
+ background: linear-gradient(to bottom, #9fef00, transparent);
+ }
+`;
+
+const StyledSvg = styled.svg`
+ pointer-events: none;
+ position: absolute;
+ inset: 0;
+ height: 100%;
+ width: 100%;
+ fill: rgba(100, 100, 100, 0.5);
+`;
+
+const StyledRect = styled.rect`
+ width: 100%;
+ height: 100%;
+ stroke-width: 0;
+`;
+
+const generateMeteor = (id: number, gridSizeX: number, gridSizeY: number) => {
+ const column = Math.floor(Math.random() * gridSizeX);
+ const startRow = Math.floor(Math.random() * (gridSizeY - 12));
+ const travelDistance = 5 + Math.floor(Math.random() * 10); // Between 5 and 15 spaces
+ const duration = 1.5 + Math.random(); // 1.5 to 2.5 seconds duration
+
+ return {
+ id,
+ column,
+ startRow,
+ endRow: startRow + travelDistance,
+ duration,
+ key: Math.random() + Math.random(),
+ };
+};
+
+const DotPattern = ({ className }: { className?: string }) => {
+ const countOfMeteors = 6;
+ const [gridSizeX, setGridSizeX] = useState(Math.floor(window.innerWidth / dotSpacing));
+ const [gridSizeY, setGridSizeY] = useState(Math.floor(window.innerHeight / dotSpacing));
+ const [meteors, setMeteors] = useState(() => Array.from({ length: countOfMeteors }, (_, index) => generateMeteor(index, gridSizeX, gridSizeY)));
+
+ const handleAnimationComplete = (id: number) => {
+ setMeteors(current =>
+ current.map(meteor => {
+ if (meteor.id === id) {
+ return generateMeteor(id, gridSizeX, gridSizeY);
+ }
+ return meteor;
+ })
+ );
+ };
+
+ useEffect(() => {
+ const handleResize = () => {
+ setGridSizeX(Math.floor(window.innerWidth / dotSpacing));
+ setGridSizeY(Math.floor(window.innerHeight / dotSpacing));
+ };
+
+ window.addEventListener('resize', handleResize);
+ return () => window.removeEventListener('resize', handleResize);
+ }, []);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {meteors.map(({ id, column, startRow, endRow, duration, key }) => (
+ handleAnimationComplete(id)}
+ />
+ ))}
+ >
+ );
+};
+
+export default DotPattern;
diff --git a/src/pages/account/index.astro b/src/pages/account/index.astro
new file mode 100644
index 0000000..65ec0c6
--- /dev/null
+++ b/src/pages/account/index.astro
@@ -0,0 +1,44 @@
+---
+import BaseLayout from '@layouts/Base.astro';
+import Nav from '@components/Nav.astro';
+
+---
+
+
+
+
+
+
+
+
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 9a6beb4..6e75e02 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,9 +1,9 @@
---
import BaseLayout from '@layouts/Base.astro';
import Nav from '@components/Nav.astro';
+import HomeBackground from '@/components/HomeBackground';
const isBossServer = import.meta.env.BOSS_SERVER === true;
-console.log('IS BOSS?', isBossServer)
const searchUrl = new URLSearchParams(new URL(Astro.request.url).search).get('url');
@@ -18,6 +18,7 @@ if (!isBossServer && searchUrl) {
{!isBossServer && ()}
+