# Project export: AetherNode

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2026
- Tagline: AetherNode powers the next generation of space data centers by intelligently scheduling compute around orbital physics.
- Devpost: https://devpost.com/software/aethernode
- GitHub: https://github.com/jeylinnn/treehacks2026
- Demo: https://drive.google.com/file/d/1ddfFnk-yus3qbqjamSpyFm2AWho2X8El/view?usp=sharing
- Video: https://www.youtube.com/embed/bo2t0RF9yMw?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 2 GitHub contributor(s) — AnonymousTerminator (2 commits), sidhantsinghvi (2 commits)

## Devpost submission (written by the team)

### Inspiration

Artificial intelligence is scaling rapidly, and the infrastructure that powers it is approaching real physical limits. Data centers already consume roughly four percent of total electricity in the United States, and by 2030 demand from AI and cloud workloads is expected to at least double. Many facilities also rely on water intensive cooling systems in regions facing water stress. Space offers a fundamentally different energy environment. In low Earth orbit, systems receive approximately 1,361 watts per square meter of direct solar radiation outside Earth’s atmosphere. However, orbital platforms operate under strict constraints, including eclipse periods roughly every ninety minutes, limited battery storage, extreme thermal swings, and intermittent ground communication windows. We were inspired by a simple question: what if compute in space were scheduled around physics instead of assuming unlimited power and cooling? Instead of treating sunlight, temperature, and connectivity as side conditions, we wanted to make them the core of decision making. That vision became AetherNode.

### What it does

AetherNode is a physics aware orchestration system for orbital edge computing. Rather than assuming compute can run continuously, it treats sunlight availability, thermal headroom, battery state, and communication windows as hard operational constraints. Our system simulates an orbital data center and continuously generates telemetry such as temperature, power levels, eclipse versus sunlight phase, and ground station connectivity. The orchestration engine evaluates these constraints in real time and determines whether high intensity AI workloads can safely execute. If temperature approaches critical limits or simulated battery levels drop during eclipse, workloads are paused or deferred. When conditions improve, compute resumes automatically. The system behaves like a mission control layer that dynamically adapts to environmental constraints. A live dashboard streams telemetry and scheduling decisions over WebSockets, allowing users to observe mission control logic operating in real time.

### How we built it

We built AetherNode using a Python backend powered by FastAPI. The system leverages asynchronous execution through asyncio to continuously evaluate system constraints and update scheduling decisions without blocking other processes. Telemetry values are generated and processed by the backend, then passed through scheduling logic that determines whether workloads should run, pause, or resume based on defined thresholds and state transitions. The frontend dashboard was built using HTML, CSS, and JavaScript. It connects to the backend via WebSockets to visualize system state, including thermal conditions, orbital phase, power status, and job execution decisions.

### Challenges we ran into

One of the biggest challenges we faced is simply how new this field is. Orbital data centers are still largely theoretical, and only in the past few years have major players like Google, Starlink, and Blue Origin begun seriously exploring large-scale space infrastructure. There is no established playbook for how compute should actually be orchestrated in orbit, no mature frameworks to study, and no production systems to benchmark against. That meant we could not rely on existing case studies or best practices. We had to dig through research papers, mission reports, and technical documentation to piece together realistic constraints around orbital mechanics, eclipse cycles, solar radiation, thermal dissipation, and ground station visibility. Because this ecosystem is still emerging, we were building from first principles rather than adapting an existing cloud architecture. Another challenge was thinking carefully about differentiation. Large aerospace and technology companies are exploring space infrastructure, satellite networks, and launch systems. However, most focus on hardware, connectivity, or transportation. We had to clearly define how AetherNode is different. Instead of competing on hardware or launch capability, we focused on the orchestration layer, the software intelligence that schedules compute around physics itself. That required us to think deeply about what layer of the stack remains unsolved and where software innovation can create meaningful leverage. Balancing ambition with practicality was also difficult. We wanted the concept to feel technically grounded and differentiated from massive aerospace players, while still building something achievable within a hackathon timeframe. This forced us to make disciplined design decisions and focus on demonstrating the core insight clearly.

### Accomplishments we're proud of

We are proud that we transformed a highly theoretical concept into a working, interactive prototype. Instead of simply discussing orbital compute at a high level, we built a functioning orchestration layer that dynamically responds to simulated sunlight cycles, thermal limits, and connectivity windows in real time. We successfully created a live mission control system that streams telemetry and scheduling decisions through an asynchronous backend. The system continuously evaluates environmental constraints and adapts compute behavior automatically, demonstrating that physics driven scheduling can be implemented in software today. Most importantly, we approached space-based computing as a systems orchestration problem rather than purely a hardware challenge. That conceptual clarity is something we are especially proud of.

### What we learned

We learned that constraint driven design is fundamentally different from traditional cloud architecture. Most modern infrastructure assumes stable power, cooling, and connectivity. Designing for orbital environments forced us to treat variability as the default state rather than the exception. We also learned how to architect asynchronous backend systems that evaluate state continuously while maintaining real time user interface updates. Coordinating telemetry generation, scheduling logic, and live dashboard streaming deepened our understanding of distributed systems thinking. Beyond technical skills, we learned how to scope an ambitious systems level idea into a focused, demonstrable prototype while maintaining conceptual depth.

### What's next

The next step is integrating real orbital data so scheduling decisions align with actual satellite trajectories and eclipse predictions. This would ground the system in real world orbital dynamics rather than purely simulated cycles. We also plan to move from threshold based logic to predictive optimization models that forecast thermal and power trends, allowing compute to be scheduled proactively instead of reactively. In the longer term, we envision expanding AetherNode to coordinate multiple orbital nodes, enabling distributed, energy aware constellations that intelligently balance workloads across satellites.

## README (from the GitHub repository)

# AetherNode

A Vite + React + TypeScript web app that renders a Cesium 3D Earth with a continuously orbiting satellite and a deterministic mission control simulation panel. All telemetry is derived from formulas and toggles (no randomness).

## Run Locally

```
npm install
npm run dev
```

Open the URL printed by Vite (usually http://localhost:5173).

## Simulation Model

The sim runs at 10 Hz. Orbit time is accelerated to a 120-second loop for visibility.

### Inputs

- `orbitPhase` advances from 0..1 based on sim time.
- `sunlight` is derived from orbit phase unless forced by toggles.
- `contactWindow` is derived from proximity to the Ground Station unless forced by toggles.
- Toggles: Sunrise, Eclipse, Thermal Warn, Thermal Halt, Cool Down, Blackout, Link Up, Solar Flare.

### Output Signals

- **Sunlight status**: `SUNLIGHT` or `ECLIPSE`.
- **Lux (0..1000)**: based on sunlight and Solar Flare; forced to 0 by Eclipse or Blackout.
- **Thermal status**: `OK`, `WARN`, or `HALT` from CPU temp and thermal toggles.
- **CPU Temp (°C)**: evolves each tick by a thermal equation.
- **Network**: `UP` when in contact window (unless Blackout), `DOWN` otherwise.
- **Contact Window**: `CONTACT` or `NO CONTACT` based on proximity.
- **Job**: `OK` or `FAILED` based on thermal limits.
- **Outbox**: pending data count that increases with compute and drains when network is `UP`.
- **Last Action**: rule-based agent action for the current tick.

### Thermal Equation

Each tick:

```
cpuTemp += (heat_in - cooling_out) * deltaSeconds
```

Where:
- `heat_in = baseHeat + workloadHeat (+ solarFlareHeat)`
- `workloadHeat` increases when jobs run (higher in sunlight).
- `cooling_out` increases when Cool Down is toggled or the agent chooses a cooldown action.
- CPU temp is clamped to 20..95°C.

### Agent Policy

Every tick, the agent decides:
1. If `cpuTemp > 88` or Thermal Halt is toggled: `thermal halt`
2. Else if `cpuTemp > 80` or Thermal Warn is toggled: `cooldown`
3. Else if `contactWindow` and outbox > 0 and network `UP`: `downlink`
4. Else if `sunlight` and thermal `OK` and network `UP`: `run job`
5. Else: `noop`

Each action writes an event log entry with a timestamp.

## Toggle Effects

- **Sunrise**: Forces sunlight `true` (overrides orbit-derived darkness unless Eclipse is also on).
- **Eclipse**: Forces sunlight `false` and Lux to 0.
- **Thermal Warn**: Forces thermal status `WARN` and biases the agent to choose `cooldown`.
- **Thermal Halt**: Forces thermal status `HALT` and immediately fails any running job.
- **Cool Down**: Increases cooling output, helping CPU temperature recover.
- **Blackout**: Forces contact window `false`, network `DOWN`, and Lux to 0.
- **Link Up**: Forces contact window `true`, network `UP`.
- **Solar Flare**: Increases heat input and Lux.

Precedence rules:
- `Eclipse` overrides `Sunrise` for sunlight and Lux.
- `Blackout` overrides `Link Up` for contact window and network.

## Cesium Scene Notes

- Earth imagery is provided by OpenStreetMap tiles (no Cesium Ion token required).
- The Sun lighting model is enabled to create day/night shading.
- The satellite follows a circular LEO path (inclination 55°) with a visible orbit track.
- A Ground Station marker is placed near 34.7°N, 120.6°W.


## Detected evidence (automated analysis)

Indexed codebase: 19 recognized source files, 49 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- React (technology) — detected in the code
- TypeScript (language) — detected in the code
- Docker (technology) — claimed on Devpost, not found in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code
- JavaScript (language) — claimed on Devpost, not found in the code
- OpenAI (technology) — claimed on Devpost, not found in the code
- Python (language) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (22 of 22)

```
index.html
package.json
README.md
src/App.tsx
src/cesium/cesium.css
src/cesium/CesiumView.tsx
src/index.css
src/main.tsx
src/sim/history.ts
src/sim/model.ts
src/sim/store.tsx
src/sim/types.ts
src/sim/whatif.ts
src/ui/GlassSelect.tsx
src/ui/MissionControl.tsx
src/ui/Pills.tsx
src/ui/TelemetryPanel.tsx
src/ui/ToggleButton.tsx
src/vite-env.d.ts
tsconfig.json
tsconfig.node.json
vite.config.ts
```

### Dependencies

- package.json: @types/react@^18.3.12, @types/react-dom@^18.3.1, @vitejs/plugin-react@^4.3.4, cesium@^1.123.1, react@^18.3.1, react-dom@^18.3.1, recharts@^2.12.7, typescript@^5.6.3, vite@^7.3.1, vite-plugin-cesium@^1.2.2

### Recent commits (newest first)

- Change project name in README
- Delete v1 directory
- Create .gitkeep
- 3d version working

## Key source files (fetched from GitHub, selected and truncated for size)

### package.json

```
{
  "name": "sun-sync-sim",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "cesium": "^1.123.1",
    "recharts": "^2.12.7",
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@types/react": "^18.3.12",
    "@types/react-dom": "^18.3.1",
    "@vitejs/plugin-react": "^4.3.4",
    "typescript": "^5.6.3",
    "vite": "^7.3.1",
    "vite-plugin-cesium": "^1.2.2"
  }
}

```

### src/main.tsx

```typescript
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
import './cesium/cesium.css';

// Cesium asset base path for Vite
(window as unknown as { CESIUM_BASE_URL?: string }).CESIUM_BASE_URL = '/cesium';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

```

### src/App.tsx

```typescript
import CesiumView from './cesium/CesiumView';
import MissionControl from './ui/MissionControl';
import TelemetryPanel from './ui/TelemetryPanel';
import { SimProvider } from './sim/store';

export default function App() {
  return (
    <SimProvider>
      <div className="app">
        <CesiumView />
        <MissionControl />
        <TelemetryPanel />
        <div className="orbit-hint">
          Orbit is simulated. Contact window toggles automatically when the satellite is near the ground station.
        </div>
      </div>
    </SimProvider>
  );
}

```

### vite.config.ts

```typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import cesium from 'vite-plugin-cesium';

export default defineConfig({
  plugins: [react(), cesium()],
  define: {
    CESIUM_BASE_URL: JSON.stringify('/cesium')
  }
});

```

### index.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Sun Sync Sim</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

```

### src/vite-env.d.ts

```typescript
/// <reference types="vite/client" />

```

### src/index.css

```css
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=Space+Grotesk:wght@400;600&display=swap');

:root {
  color-scheme: dark;
  --bg: #04080f;
  --panel: rgba(6, 14, 22, 0.78);
  --panel-border: rgba(70, 170, 255, 0.35);
  --accent: #39d0ff;
  --accent-soft: rgba(57, 208, 255, 0.15);
  --warning: #ffb347;
  --danger: #ff5d5d;
  --ok: #6af3b5;
  --muted: #9bb3c9;
  --text: #e9f5ff;
}

* {
  box-sizing: border-box;
}

html,
body,
#root {
  height: 100%;
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Space Grotesk', 'Trebuchet MS', 'Segoe UI', sans-serif;
}

.app {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.orbit-hint {
  position: absolute;
  left: 16px;
  bottom: 16px;
  background: rgba(0, 8, 16, 0.65);
  border: 1px solid rgba(57, 208, 255, 0.2);
  padding: 8px 12px;
  border-radius: 10px;
  font-size: 12px;
  color: var(--muted);
  backdrop-filter: blur(6px);
}

.mission-panel {
  position: absolute;
  top: 16px;
  left: 16px;
  width: min(420px, 92vw);
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  padding: 14px 14px 12px 14px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45), 0 0 18px rgba(57, 208, 255, 0.15);
  backdrop-filter: blur(8px);
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.panel-title {
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 13px;
  color: var(--accent);
}

.panel-controls {
  display: flex;
  gap: 8px;
}

.control-button {
  border: 1px solid rgba(57, 208, 255, 0.35);
  background: rgba(7, 18, 30, 0.8);
  color: var(--text);
  font-size: 11px;
  padding: 6px 10px;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
}

.control-button.active {
  background: linear-gradient(135deg, rgba(57, 208, 255, 0.3), rgba(57, 208, 255, 0.12));
  border-color: rgba(57, 208, 255, 0.7);
  color: #eaffff;
}

.status-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  row-gap: 8px;
  column-gap: 12px;
  margin-bottom: 8px;
  font-size: 13px;
}

.status-label {
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 11px;
}

.job-name {
  margin: 6px 0 10px 0;
  font-size: 12px;
  color: var(--muted);
}

.toggle-section {
  margin-top: 8px;
  border-top: 1px solid rgba(57, 208, 255, 0.12);
  padding-top: 8px;
}

.toggle-title {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--accent);
  margin-bottom: 6px;
}

.toggle-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}

.toggle-button {
  border: 1px solid rgba(57, 208, 255, 0.25);
  background: rgba(8, 14, 22, 0.65);
  color: var(--text);
  font-size: 11px;
  padding: 6px 10px;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: all 0.2s ease;
}

.toggle-button:hover {
  border-color: rgba(57, 208, 255, 0.6);
}

.toggle-button.active {
  background: rgba(57, 208, 255, 0.22);
  border-color: rgba(57, 208, 255, 0.85);
  box-shadow: 0 0 14px rgba(57, 208, 255, 0.3);
}

.pill {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 1px solid transparent;
  background: rgba(10, 18, 26, 0.8);
}

.pill.ok {
  color: #0cff9a;
  border-color: rgba(10, 255, 154, 0.5);
  background: rgba(10, 255, 154, 0.12);
}

.pill.warn {
  color: var(--warning);
  border-color: rgba(255, 179, 71, 0.6);
  background: rgba(255, 179, 71, 0.12);
}

.pill.halt,
.pill.down,
.pill.failed {
  color: var(--danger);
  border-color: rgba(255, 93, 93, 0.6);
  background: rgba(255, 93, 93, 0.12);
}

.pill.sun {
  color: #ffe58a;
  border-color: rgba(255, 229, 138, 0.6);
  background: rgba(255, 229, 138, 0.14);
}

.pill.eclipse,
.pill.nocontact {
  color: #6cb1ff;
  border-color: rgba(108, 177, 255, 0.6);
  background: rgba(108, 177, 255, 0.12);
}

.pill.up,
.pill.contact {
  color: #7ef7ff;
  border-color: rgba(126, 247, 255, 0.6);
  background: rgba(126, 247, 255, 0.12);
}

.pill.neutral {
  color: var(--muted);
  border-color: rgba(155, 179, 201, 0.4);
  background: rgba(155, 179, 201, 0.12);
}

.event-log {
  border-top: 1px solid rgba(57, 208, 255, 0.12);
  margin-top: 10px;
  padding-top: 8px;
}

.event-line {
  font-family: 'IBM Plex Mono', 'SFMono-Regular', Menlo, monospace;
  font-size: 11px;
  color: #b7d2e3;
  margin-bottom: 4px;
}

.telemetry-panel {
  position: absolute;
  top: 16px;
  right: 16px;
  width: min(420px, 36vw);
  display: flex;
  flex-direction: column;
  gap: 12px;
  pointer-events: auto;
}

.telemetry-card {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  padding: 12px 12px 10px 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45), 0 0 18px rgba(57, 208, 255, 0.12);
  backdrop-filter: blur(8px);
}

.telemetry-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.telemetry-title {
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 12px;
  color: var(--accent);
}

.telemetry-controls {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
}

.telemetry-chart {
  width: 100%;
  height: 210px;
}

.glassSelect {
  position: relative;
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  background: rgba(8, 14, 22, 0.55);
  border: 1px solid rgba(57, 208, 255, 0.3);
  box-shadow: 0 0 12px rgba(57, 208, 255, 0.12);
  backdrop-filter: blur(8px);
}

.glassSelect select {
  background: transparent;
  color: var(--text);
  border: none;
  padding: 7px 32px 7px 14px;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: none;
  appearance: none;
  -we
[truncated — 754 more characters]
```

### src/cesium/cesium.css

```css
#cesiumContainer {
  position: absolute;
  inset: 0;
}

.cesium-viewer,
.cesium-viewer-cesiumWidgetContainer,
.cesium-widget {
  width: 100%;
  height: 100%;
}

```

### src/ui/Pills.tsx

```typescript
import React from 'react';

export function Pill({ label, tone = 'neutral' }: { label: string; tone?: string }) {
  return <span className={`pill ${tone}`}>{label}</span>;
}

```

### src/ui/ToggleButton.tsx

```typescript
import React from 'react';

interface ToggleButtonProps {
  label: string;
  active: boolean;
  onClick: () => void;
}

export default function ToggleButton({ label, active, onClick }: ToggleButtonProps) {
  return (
    <button className={`toggle-button ${active ? 'active' : ''}`} onClick={onClick} type="button">
      {label}
    </button>
  );
}

```

[9 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]