diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index fde7398..d05ed9c 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -15,6 +15,7 @@ export const metadata: Metadata = {
};
import ErrorBoundaryNavigation from "@/components/ErrorBoundaryNavigation";
+import Starfield from "@/components/starBackground/Starfield";
export default function RootLayout({
children,
@@ -27,7 +28,10 @@ export default function RootLayout({
- {children}
+
+
+ {children}
+
diff --git a/frontend/src/app/satellites/page.tsx b/frontend/src/app/satellites/page.tsx
index 01809c0..084665f 100644
--- a/frontend/src/app/satellites/page.tsx
+++ b/frontend/src/app/satellites/page.tsx
@@ -5,6 +5,7 @@ import Link from "next/link";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import SatelliteStatsTable from "@/components/ui/satelliteStatsTable";
import Image from "next/image";
+
const HOST_URL = process.env.HOST_URL;
const GET_SATELLITES = gql(`
query GET_SATELLITES {
diff --git a/frontend/src/components/starBackground/Starfield.tsx b/frontend/src/components/starBackground/Starfield.tsx
new file mode 100644
index 0000000..c7fa3fa
--- /dev/null
+++ b/frontend/src/components/starBackground/Starfield.tsx
@@ -0,0 +1,167 @@
+"use client";
+
+import React, { useEffect } from "react";
+
+interface Props {
+ speedFactor?: number;
+ backgroundColor?: string;
+ starColor?: [number, number, number];
+ starCount?: number;
+}
+
+export default function Starfield(props: Props) {
+ const {
+ speedFactor = 0.05,
+ backgroundColor = "black",
+ starColor = [255, 255, 255],
+ starCount = 5000,
+ } = props;
+
+ useEffect(() => {
+ const canvas = document.getElementById(
+ "starfield",
+ ) as HTMLCanvasElement;
+
+ if (canvas) {
+ const c = canvas.getContext("2d");
+
+ if (c) {
+ let w = window.innerWidth;
+ let h = window.innerHeight;
+
+ const setCanvasExtents = () => {
+ canvas.width = w;
+ canvas.height = h;
+ };
+
+ setCanvasExtents();
+
+ window.onresize = () => {
+ setCanvasExtents();
+ };
+
+ const makeStars = (count: number) => {
+ const out = [];
+ for (let i = 0; i < count; i++) {
+ const s = {
+ x: Math.random() * 1600 - 800,
+ y: Math.random() * 900 - 450,
+ z: Math.random() * 1000,
+ };
+ out.push(s);
+ }
+ return out;
+ };
+
+ let stars = makeStars(starCount);
+
+ const clear = () => {
+ c.fillStyle = backgroundColor;
+ c.fillRect(0, 0, canvas.width, canvas.height);
+ };
+
+ const putPixel = (x: number, y: number, brightness: number) => {
+ const rgb =
+ "rgba(" +
+ starColor[0] +
+ "," +
+ starColor[1] +
+ "," +
+ starColor[2] +
+ "," +
+ brightness +
+ ")";
+ c.fillStyle = rgb;
+ c.fillRect(x, y, 1, 1);
+ };
+
+ const moveStars = (distance: number) => {
+ const count = stars.length;
+ for (var i = 0; i < count; i++) {
+ const s = stars[i];
+ s.z -= distance;
+ while (s.z <= 1) {
+ s.z += 1000;
+ }
+ }
+ };
+
+ let prevTime: number;
+ const init = (time: number) => {
+ prevTime = time;
+ requestAnimationFrame(tick);
+ };
+
+ const tick = (time: number) => {
+ let elapsed = time - prevTime;
+ prevTime = time;
+
+ moveStars(elapsed * speedFactor);
+
+ clear();
+
+ const cx = w / 2;
+ const cy = h / 2;
+
+ const count = stars.length;
+ for (var i = 0; i < count; i++) {
+ const star = stars[i];
+
+ const x = cx + star.x / (star.z * 0.001);
+ const y = cy + star.y / (star.z * 0.001);
+
+ if (x < 0 || x >= w || y < 0 || y >= h) {
+ continue;
+ }
+
+ const d = star.z / 1000.0;
+ const b = 1 - d * d;
+
+ putPixel(x, y, b);
+ }
+
+ requestAnimationFrame(tick);
+ };
+
+ requestAnimationFrame(init);
+
+ // add window resize listener:
+ window.addEventListener("resize", function () {
+ w = window.innerWidth;
+ h = window.innerHeight;
+ setCanvasExtents();
+ });
+ } else {
+ console.error("Could not get 2d context from canvas element");
+ }
+ } else {
+ console.error('Could not find canvas element with id "starfield"');
+ }
+
+ return () => {
+ window.onresize = null;
+ };
+ }, [starColor, backgroundColor, speedFactor, starCount]);
+
+ return (
+
+ );
+}
+
+// https://github.com/designly1/react-starfield
+// MIT License