diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..a3d42ba
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,6 @@
+# Copy this file to .env and fill in real values.
+
+NASA_API_KEY=YOUR_NASA_API_KEY
+ASTRONOMY_API_APP_ID=YOUR_ASTRONOMY_API_APP_ID
+ASTRONOMY_API_APP_SECRET=YOUR_ASTRONOMY_API_APP_SECRET
+PORT=8080
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8531826
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+# Maven / Java build output
+target/
+*.class
+*.jar
+*.war
+*.ear
+
+# IDE files
+.idea/
+.vscode/
+.settings/
+.classpath
+.project
+
+# OS files
+.DS_Store
+Thumbs.db
+
+# Logs
+*.log
+
+# Local secrets / env
+.env
+.env.*
+!.env.example
+src/main/resources/application-local.properties
+src/main/resources/secrets.properties
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e9cc6c9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 End Nightshade
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 0e29bee..468d715 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,26 @@
-# APCSA-Final
-Final for APCSA
+# APCSA Final Project
+
+Space Mission and Event Tracker (website, with possible mobile app version later).
+
+## What it does
+- Pulls live data from space APIs
+- Lets users search/filter missions and events
+
+## APIs
+- The Space Devs Launch Library 2
+- NASA Open APIs
+- AstronomyAPI
+
+## Tech
+- Java 21
+- Spring Boot + Thymeleaf
+- Maven
+- Mobile app version (possible future phase)
+
+## Goal
+Make space mission + astronomy event info easy to view in one place.
+
+## Run locally
+- Put your NASA key in `.env` or export `NASA_API_KEY`
+- Start app: `mvn spring-boot:run`
+- Open: `http://localhost:8080`
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..b0c8b2b
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,48 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.3.5
+
+
+
+ com.apcsa
+ space-tracker
+ 0.0.1-SNAPSHOT
+ space-tracker
+ APCSA final project: Space Mission and Event Tracker
+
+
+ 21
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/src/main/java/com/apcsa/spacetracker/SpaceTrackerApplication.java b/src/main/java/com/apcsa/spacetracker/SpaceTrackerApplication.java
new file mode 100644
index 0000000..7e9993a
--- /dev/null
+++ b/src/main/java/com/apcsa/spacetracker/SpaceTrackerApplication.java
@@ -0,0 +1,11 @@
+package com.apcsa.spacetracker;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpaceTrackerApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(SpaceTrackerApplication.class, args);
+ }
+}
diff --git a/src/main/java/com/apcsa/spacetracker/controller/HomeController.java b/src/main/java/com/apcsa/spacetracker/controller/HomeController.java
new file mode 100644
index 0000000..a4baafd
--- /dev/null
+++ b/src/main/java/com/apcsa/spacetracker/controller/HomeController.java
@@ -0,0 +1,28 @@
+package com.apcsa.spacetracker.controller;
+
+import com.apcsa.spacetracker.model.ApodResponse;
+import com.apcsa.spacetracker.service.NasaService;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class HomeController {
+ private final NasaService nasaService;
+
+ public HomeController(NasaService nasaService) {
+ this.nasaService = nasaService;
+ }
+
+ @GetMapping("/")
+ public String home(Model model) {
+ try {
+ ApodResponse apod = nasaService.getApod();
+ model.addAttribute("apod", apod);
+ } catch (Exception ex) {
+ model.addAttribute("error", "Could not load NASA APOD right now.");
+ }
+
+ return "index";
+ }
+}
diff --git a/src/main/java/com/apcsa/spacetracker/model/ApodResponse.java b/src/main/java/com/apcsa/spacetracker/model/ApodResponse.java
new file mode 100644
index 0000000..fbcec71
--- /dev/null
+++ b/src/main/java/com/apcsa/spacetracker/model/ApodResponse.java
@@ -0,0 +1,58 @@
+package com.apcsa.spacetracker.model;
+
+public class ApodResponse {
+ private String title;
+ private String date;
+ private String explanation;
+ private String url;
+ private String hdurl;
+ private String media_type;
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDate() {
+ return date;
+ }
+
+ public void setDate(String date) {
+ this.date = date;
+ }
+
+ public String getExplanation() {
+ return explanation;
+ }
+
+ public void setExplanation(String explanation) {
+ this.explanation = explanation;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getHdurl() {
+ return hdurl;
+ }
+
+ public void setHdurl(String hdurl) {
+ this.hdurl = hdurl;
+ }
+
+ public String getMedia_type() {
+ return media_type;
+ }
+
+ public void setMedia_type(String media_type) {
+ this.media_type = media_type;
+ }
+}
diff --git a/src/main/java/com/apcsa/spacetracker/service/NasaService.java b/src/main/java/com/apcsa/spacetracker/service/NasaService.java
new file mode 100644
index 0000000..51b5b69
--- /dev/null
+++ b/src/main/java/com/apcsa/spacetracker/service/NasaService.java
@@ -0,0 +1,27 @@
+package com.apcsa.spacetracker.service;
+
+import com.apcsa.spacetracker.model.ApodResponse;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+@Service
+public class NasaService {
+ private final RestTemplate restTemplate;
+ private final String nasaApiKey;
+
+ public NasaService(@Value("${nasa.api.key}") String nasaApiKey) {
+ this.restTemplate = new RestTemplate();
+ this.nasaApiKey = nasaApiKey;
+ }
+
+ public ApodResponse getApod() {
+ String url = UriComponentsBuilder
+ .fromHttpUrl("https://api.nasa.gov/planetary/apod")
+ .queryParam("api_key", nasaApiKey)
+ .toUriString();
+
+ return restTemplate.getForObject(url, ApodResponse.class);
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..753645b
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+spring.application.name=space-tracker
+server.port=${PORT:8080}
+
+# Pull from environment variables; safe defaults for local dev.
+nasa.api.key=${NASA_API_KEY:DEMO_KEY}
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
new file mode 100644
index 0000000..0ef7cbf
--- /dev/null
+++ b/src/main/resources/templates/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+ SpaceTracker
+
+
+
+
+
+
+
SpaceTracker
+
Java Spring Boot site for space missions and astronomy events.
+
+
APCSA Final
+
+
+ Could not load NASA APOD right now.
+
+
+ NASA APOD
+ date
+ title
+ explanation
+
+
+ APOD today is not an image. Open:
+ NASA link
+
+
+
+
+