A Consumer-Focused Amateur Astronomy & Citizen Science Platform
SpaceExplorer 3.0 is a full-stack web application designed to democratize amateur astronomy and citizen science participation. With an immersive HUD aesthetic and gamification system, it enables astronomy enthusiasts to log observations, contribute to citizen science programs, track space launches, discover new celestial objects, and compete on global leaderboards.
- Overview
- Features
- Tech Stack
- Project Structure
- Installation & Setup
- Configuration
- API Documentation
- Database Schema
- Frontend Pages & Features
- Gamification System
- Development Guide
- Known Issues & Limitations
- Remaining Tasks for Production Excellence
- Contributing
SpaceExplorer 3.0 serves as a bridge between casual astronomy enthusiasts and serious citizen science participants. The platform:
- Logs Observations: Record telescope observations with detailed metadata (equipment, location, seeing conditions)
- Tracks Citizen Science: Document contributions to NASA and other research programs
- Follows Space Launches: Stay updated on live rocket launches and space missions
- Shares Discoveries: Report astronomical anomalies, exoplanet findings, and celestial discoveries
- Gamifies Engagement: Earn points, unlock levels, and compete on leaderboards
- Builds Community: Connect with other amateur astronomers through a community directory
- Offline-First Architecture: Continues working when backend is unreachable, syncing when reconnected
-
Observation Logging System: Record celestial object observations with:
- Object name, type, and coordinates
- Equipment used (telescope specs)
- Seeing conditions (Bortle scale 1-9)
- Detailed notes and subjective ratings
- Automatic timestamp and location tracking
-
Citizen Science Hub: Track participation in programs like:
- NASA Exoplanet Watch
- Light curve analysis
- Transit candidate validation
- Custom citizen science programs
-
Discovery System: Report and share astronomical discoveries:
- Exoplanet candidates
- Anomalies and thermal vents
- New stellar objects
- Significant astronomical events
-
Launch Companion:
- Track upcoming space launches
- Follow specific missions
- Real-time launch countdowns
- Mission details and statistics
-
Points System: Earn rewards for:
- Logging observations (20 points)
- Citizen science contributions (50 points)
- Discovery reports (40 points)
- Streak bonuses
-
Leveling System: Progress through ranks:
- Cadet → Pilot → Specialist → Commander → Admiral
-
Leaderboard: Rank-based competition showing:
- Top contributors by points
- Observation counts
- Citizen science contributions
- Observation streak tracking
-
Community Directory:
- Browse astronomy club members
- Connect with fellow observers
- Share experience levels
-
Registration & Authentication:
- Secure JWT-based authentication
- Email verification ready
- Role-based access (user/admin)
-
User Profiles:
- Customizable profile information
- Points and level tracking
- Activity history
-
Advanced Search:
- Search observations and discoveries
- Filter by type, date, location
- Text-based full search capabilities
- Database browser interface
-
Offline Search: Access previously cached data when offline
-
Observer Dashboard:
- Recent activities summary
- Quick stats on contributions
- Observation trending
- Achievement badges
-
Charts & Visualizations:
- Observation frequency charts
- Points earned over time
- Contribution breakdown
- Runtime: Node.js
- Framework: Express.js 5.x
- Database: MongoDB (with Mongoose ODM)
- Authentication: JWT (jsonwebtoken)
- Security: bcryptjs for password hashing
- Validation: express-validator
- Utilities: dotenv for configuration, CORS for cross-origin requests
- Development: nodemon for auto-reload
- Markup: HTML5 with semantic structure
- Styling: CSS3 with CSS Grid/Flexbox
- JavaScript: Vanilla JS (no framework dependencies)
- Visualization: Chart.js for data visualization
- Animations: tsparticles for particle background effects
- State Management: localStorage for client-side caching
- Version Control: Git
- Environment: .env configuration
- Port: Default 5000 (configurable)
SpaceExplorer3.0/
├── README.md # Project documentation
├── backend/
│ ├── package.json # Node dependencies and scripts
│ ├── server.js # Express app entry point
│ ├── seed.js # Database initialization script
│ ├── config/
│ │ └── db.js # MongoDB connection setup
│ ├── middleware/
│ │ └── auth.js # JWT authentication middleware
│ ├── models/ # Mongoose schemas
│ │ ├── User.js # User account schema
│ │ ├── Observation.js # Telescope observation schema
│ │ ├── CitizenContribution.js # Citizen science contribution schema
│ │ ├── Discovery.js # Astronomical discovery schema
│ │ ├── FollowedLaunch.js # User launch tracking schema
│ │ ├── PointsLog.js # Points transaction history
│ │ └── CommunityMember.js # Community directory schema
│ └── routes/ # API endpoints
│ ├── auth.js # Registration, login, profile
│ ├── observation.js # Observation CRUD operations
│ ├── citizen.js # Citizen science logging
│ ├── discovery.js # Discovery reporting
│ ├── launch.js # Launch tracking
│ ├── leaderboard.js # Ranking and statistics
│ └── crew.js # Community directory
│
└── frontend/
├── index.html # Main HTML shell
├── scripts/
│ ├── api.js # API client with offline support
│ ├── router.js # Frontend page routing
│ ├── components.js # Reusable UI components
│ ├── charts.js # Chart.js wrapper functions
│ ├── countdown.js # Launch countdown timer
│ ├── data.js # Mock data and utilities
│ └── pages/
│ ├── dashboard.js # Observer dashboard page
│ ├── observations.js # Observation log page
│ ├── discoveries.js # Citizen science hub
│ ├── launches.js # Live launches companion
│ ├── leaderboard.js # Ranking page
│ ├── search.js # Search & database browser
│ └── login.js # Account & sync page
└── styles/
├── base.css # CSS custom properties and resets
├── layout.css # Grid/flex layouts
├── components.css # Button, card, form styling
├── pages.css # Page-specific styles
└── animations.css # Transitions and keyframe animations
- Node.js 16+ (verify with
node --version) - MongoDB running locally or MongoDB Atlas account
- Git for version control
- npm or yarn package manager
# Clone the repository (if using git)
git clone <repository-url>
cd SpaceExplorer3.0
# Install backend dependencies
cd backend
npm install
# Install frontend dependencies (if any package.json exists in frontend)
cd ../frontend
npm install # (optional, frontend uses CDN scripts)
cd ..Create a .env file in the backend/ directory:
cd backend
touch .envAdd the following variables (see Configuration section below for details):
# MongoDB Connection
MONGO_URI=mongodb://localhost:27017/space-explorer
# Or use MongoDB Atlas:
# MONGO_URI=mongodb+srv://<username>:<password>@cluster0.mongodb.net/space-explorer
# Server Configuration
PORT=5000
NODE_ENV=development
# JWT Configuration
JWT_SECRET=your_jwt_secret_key_here_change_in_production
JWT_EXPIRE=1d
# Frontend Configuration (optional)
FRONTEND_URL=http://localhost:3000# Seed initial database with sample data
cd backend
npm run seed.js
# OR with node directly:
node seed.jsThis will:
- Connect to MongoDB
- Clear existing collections
- Create sample users (commander/test@space.com)
- Create sample observations and discoveries
- Initialize points logs
cd backend
# Development with auto-reload
npm run dev
# Production
npm startOutput should show:
SpaceExplorer server running on port 5000
MongoDB Compass Connected Cleanly...
- Open
frontend/index.htmlin your web browser - Or serve it using a simple HTTP server:
# Using Python 3
cd frontend
python -m http.server 8000
# Using Node http-server
npx http-server frontend -p 8000Then navigate to http://localhost:8000
Use the seeded credentials:
- Email: test@space.com
- Password: password123
- Role: user (level: pilot)
Or register a new account through the UI.
| Variable | Default | Description | Required |
|---|---|---|---|
MONGO_URI |
mongodb://localhost:27017/space-explorer |
MongoDB connection string | ✅ Yes |
PORT |
5000 |
HTTP server port | No |
NODE_ENV |
development |
Environment mode (development/production) | No |
JWT_SECRET |
N/A | Secret key for JWT signing | Yes |
JWT_EXPIRE |
1d |
JWT expiration time | No |
CORS_ORIGIN |
* |
CORS allowed origins | No |
Located in frontend/scripts/api.js:
const API_BASE = 'http://localhost:5000/api';Change this if your backend runs on a different URL.
# On Windows (if MongoDB installed)
mongod
# On macOS with Homebrew
brew services start mongodb-community
# On Linux
sudo systemctl start mongod- Create a cluster at https://www.mongodb.com/cloud/atlas
- Create a database user
- Get connection string
- Add to
.env:MONGO_URI=mongodb+srv://username:password@cluster.mongodb.net/space-explorer
http://localhost:5000/api
All protected endpoints require the Authorization header:
Authorization: Bearer <JWT_TOKEN>
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /auth/register |
NO | Register new user |
| POST | /auth/login |
NO | Login and get JWT token |
| GET | /auth/me |
YES | Get current user profile |
POST /auth/register
{
"email": "user@example.com",
"password": "securepass123",
"username": "astronomer42"
}POST /auth/login
{
"email": "user@example.com",
"password": "securepass123"
}Response:
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "507f1f77bcf86cd799439011",
"username": "astronomer42",
"email": "user@example.com",
"role": "user",
"totalPoints": 0,
"level": "cadet"
}
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
✅ | Get user's observations |
| POST | / |
✅ | Log new observation |
| DELETE | /:id |
✅ | Delete observation |
POST /observations (Log new observation)
{
"objectName": "Orion Nebula (M42)",
"objectType": "Nebula",
"locationName": "Dark Sky Observatory",
"equipment": "8-inch Dobsonian",
"seeing": "Good",
"bortleScale": 3,
"notes": "Trapezium cluster clearly resolved.",
"rating": 5
}Response:
{
"_id": "507f1f77bcf86cd799439011",
"objectName": "Orion Nebula (M42)",
"createdBy": "507f1f77bcf86cd799439012",
"points": 20,
"observedAt": "2026-09-01T10:30:00Z"
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
YES | Get user's contributions |
| POST | / |
YES | Log citizen science contribution |
POST /citizen (Log contribution)
{
"programId": "nasa-exoplanet-watch",
"programName": "Exoplanet Watch",
"description": "Analyzed light curve data for transit candidate",
"link": "https://exoplanets.nasa.gov"
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
NO | Get all discoveries |
| POST | / |
YES | Report new discovery |
| DELETE | /:id |
YES | Delete discovery |
POST /discoveries (Report discovery)
{
"title": "Ares Thermal Rift Anomaly",
"type": "anomaly",
"location": "Mars Quadrant Delta-4",
"description": "Subsurface thermal vents detected with liquid elements.",
"significance": "High trace biosignature indicators."
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
YES | Get user's followed launches |
| POST | / |
YES | Follow a launch |
| DELETE | /:launchId |
YES | Unfollow launch |
POST /launches (Follow launch)
{
"launchId": "SpaceX-Starship-IFT5"
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
NO | Get top 15 contributors |
Response:
[
{
"username": "commander",
"totalPoints": 500,
"level": "commander",
"totalObservations": 23,
"totalCitizenScience": 8,
"observationDays": 15
}
]| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
❌ | Get community members |
| GET | /:userId |
❌ | Get member details |
To be implemented - Will support full-text search across observations, discoveries, and users.
{
_id: ObjectId,
username: String (unique, required),
email: String (unique, required, lowercase),
passwordHash: String (required, bcrypt hashed),
role: String (enum: ['user', 'admin'], default: 'user'),
totalPoints: Number (default: 0),
level: String (default: 'cadet'), // cadet, pilot, specialist, commander, admiral
createdAt: Date (auto),
updatedAt: Date (auto)
}{
_id: ObjectId,
createdBy: ObjectId (ref: User, required, indexed),
objectName: String (required),
objectType: String (required),
locationName: String,
equipment: String,
seeing: String,
bortleScale: Number (1-9),
notes: String,
rating: Number (1-5),
observedAt: Date (default: now),
createdAt: Date (auto),
updatedAt: Date (auto),
// Indexes: { createdBy: 1, observedAt: -1 }
}{
_id: ObjectId,
userId: ObjectId (ref: User, required, indexed),
programId: String (required),
programName: String (required),
description: String (required),
link: String (URL),
date: Date (default: now),
// Indexes: { userId: 1, date: -1 }
}{
_id: ObjectId,
title: String (required),
type: String (required), // exoplanet, anomaly, star, etc.
location: String (required),
discoveredBy: ObjectId (ref: User),
description: String,
significance: String,
createdAt: Date (default: now),
// Indexes:
// - { type: 1 }
// - { type: 1, createdAt: -1 }
// - text index on { title, description }
}{
_id: ObjectId,
userId: ObjectId (ref: User, required),
launchId: String (required),
followedAt: Date (default: now),
// Indexes: { userId: 1, launchId: 1 } (unique)
}{
_id: ObjectId,
userId: ObjectId (ref: User, required, indexed),
action: String (required), // OBSERVATION_LOGGED, CITIZEN_SCIENCE_LOGGED, DISCOVERY_LOGGED
points: Number (required),
sourceId: ObjectId (reference to the action source),
createdAt: Date (default: now),
// Indexes: { userId: 1, createdAt: -1 }
}{
_id: ObjectId,
userId: ObjectId (ref: User, required),
bio: String,
equipmentList: [String],
location: String,
telescope: String,
experience: String (beginner, intermediate, advanced),
joinedAt: Date (default: now)
}- Quick stats on total observations, discoveries, and points
- Recent activity feed
- Achievement summary
- Quick action buttons
- Form to log new telescope observations
- List of user's past observations
- Filters by date, object type
- Delete/edit capabilities
- Browse all citizen science contributions
- Report new discoveries
- Discovery details modal
- Filter by discovery type (exoplanet, anomaly, etc.)
- Real-time countdown timers for upcoming launches
- Launch details (mission name, date, time)
- Follow/unfollow launches
- Auto-refresh during countdowns
- Browse registered astronomy club members
- Filter by experience level
- View member profiles
- See member statistics
- Top 15 contributors ranked by points
- Display levels and badges
- Sort by observations, citizen science contributions
- Approximate streak calculations
- Global search across all observations
- Advanced filters (type, date range, location)
- Database browser interface
- Browse discoveries and contributions
- User registration form
- Login form with JWT token storage
- Profile view/edit
- Logout functionality
- Session sync status indicator
| Action | Points | Cap |
|---|---|---|
| Log Observation | 20 | Unlimited |
| Citizen Science Contribution | 50 | Unlimited |
| Report Discovery | 40 | Unlimited |
| Observation Streak (7 days) | 50 | Once per period |
Points Range → Level → Rank Icon
0-99 → Cadet → 🌟
100-249 → Pilot → 🌟🌟
250-499 → Specialist → 🌟🌟🌟
500-999 → Commander → 🌟🌟🌟🌟
1000+ → Admiral → 🌟🌟🌟🌟🌟
- First observation
- Week of observations
- 100 points milestone
- 10 citizen science contributions
- Discovery recognized by admin
Currently, no automated tests exist. See TODO section below.
- Backend: Follow Express.js conventions, ES6+ syntax
- Frontend: Vanilla JS with clear naming conventions
- Naming: camelCase for variables/functions, PascalCase for classes/models
- Comments: JSDoc for complex functions
Example: Adding a new /api/weather endpoint
- Create
backend/routes/weather.js:
const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
router.get('/', auth, async (req, res) => {
try {
// Route logic here
res.json({ message: 'Weather data' });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
module.exports = router;- Register in
backend/server.js:
app.use('/api/weather', require('./routes/weather'));- Create API wrapper in
frontend/scripts/api.js:
async function getWeather() {
return await apiGet('/weather', 'cache_weather');
}- Create
backend/models/MyModel.js:
const mongoose = require('mongoose');
const MyModelSchema = new mongoose.Schema({
field1: { type: String, required: true },
field2: { type: Number, default: 0 },
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
}, { timestamps: true });
MyModelSchema.index({ userId: 1, createdAt: -1 });
module.exports = mongoose.model('MyModel', MyModelSchema);- Add to
backend/seed.jsif needed - Create corresponding API route
- Create
frontend/scripts/pages/mypage.js:
async function initMyPage() {
console.log('Loading My Page...');
// Page initialization logic
}- Register in
frontend/scripts/router.js:
const PAGES = {
'mypage': { title: 'My Page', module: () => initMyPage() },
// ... other pages
};- Add navigation button in
frontend/index.html:
<button class="nav-item" data-page="mypage" aria-label="My Page">
<div class="nav-icon"><!-- SVG icon --></div>
<span class="nav-label">My Page</span>
</button>-
No Real Launch Data: Launch information is mocked. Integration with rocketlaunch.live or similar API needed.
-
No Email Verification: Email uniqueness is enforced at DB level, but no confirmation emails sent.
-
Limited Search: Full-text search not yet implemented. Currently basic filtering only.
-
No Image Upload: Observations can't include photos or sketches yet.
-
Frontend Performance: No pagination—all data loaded at once (issue at scale >1000 records).
-
No Rate Limiting: API endpoints lack rate limiting, vulnerable to spam.
-
Offline Sync: Offline edits not fully implemented—read-only offline mode works.
-
No Push Notifications: Launch countdowns require manual refresh.
-
Mobile Responsive: Partially responsive but not fully mobile-optimized.
-
No Admin Dashboard: Admin role exists but no admin-specific tools/interface.
- Empty observation list may not display properly in UI
- JWT token doesn't refresh; session ends after 24 hours
- Leaderboard aggregation may timeout with large datasets (>10k users)
- CORS errors when frontend URL differs from API_BASE
-
Real Launch Data Integration
- Integrate rocketlaunch.live or SpaceX API
- Real-time countdown updates
- Actual mission details and images
- Estimated effort: 8-12 hours
-
Email Verification & Reset
- Implement email sending (nodemailer/SendGrid)
- Confirmation token system
- Password reset flow
- Estimated effort: 6-8 hours
-
Database Optimization
- Create proper database indexes
- Test query performance
- Implement pagination (page, limit)
- Estimated effort: 4-6 hours
-
Error Handling & Logging
- Implement winston or bunyan logger
- Global error handler middleware
- Better error messages in UI
- Estimated effort: 4-6 hours
-
Environment Variable Validation
- Validate .env file on startup
- Clear error if MONGO_URI/JWT_SECRET missing
- Estimated effort: 2-3 hours
-
Authentication Improvements
- Token refresh mechanism (refresh tokens)
- Session management
- Remember me functionality
- Multi-device login handling
- Estimated effort: 6-8 hours
-
Testing Suite
- Jest/Mocha setup
- Unit tests for models (70%+ coverage)
- API endpoint tests
- Frontend component tests
- Estimated effort: 16-20 hours
-
Rate Limiting & Security
- Implement express-rate-limit
- Input validation on all endpoints
- SQL injection/NoSQL injection prevention (already using Mongoose)
- CSRF protection if needed
- Estimated effort: 6-8 hours
-
Pagination & Infinite Scroll
- Add
pageandlimitquery parameters - Implement cursor-based pagination
- Update frontend to handle pagination
- Estimated effort: 6-8 hours
- Add
-
Image Upload System
- Integrate multer for file handling
- Support for observation sketches/photos
- Resize/optimize images
- Cloud storage (AWS S3 or Firebase)
- Estimated effort: 10-14 hours
-
Admin Dashboard
- Create admin-only pages
- User management interface
- Discovery/observation moderation
- Points audit interface
- Statistics dashboard
- Estimated effort: 16-20 hours
-
Responsive Design Overhaul
- Mobile-first CSS refactor
- Test on iPhone/Android
- Touch-friendly navigation
- Tablet optimization
- Estimated effort: 12-16 hours
-
Search Implementation
- Full-text search across observations
- Discovery search with filters
- User search in community directory
- Elastic search integration (for scale)
- Estimated effort: 8-12 hours
-
Push Notifications
- WebSocket for real-time launch updates
- Browser push notifications
- Email digest of new discoveries
- Estimated effort: 10-12 hours
-
Data Visualization
- Observation frequency charts
- Points over time graph
- Observation type breakdown
- Leaderboard trends
- Estimated effort: 6-8 hours
-
Export/Import
- Export observations as CSV/JSON
- Backup user data
- Import observations from CSV
- Estimated effort: 4-6 hours
-
Social Features
- Follow other astronomers
- Comment on observations/discoveries
- Observation groups/clubs
- Share to social media
- Estimated effort: 12-16 hours
-
Advanced Gamification
- Achievement badges
- Streak tracking
- Points challenges
- Monthly rankings
- Estimated effort: 8-10 hours
-
API Documentation
- Swagger/OpenAPI specification
- Interactive API explorer
- Code examples in multiple languages
- Estimated effort: 6-8 hours
-
Analytics & Metrics
- Track user engagement
- Observation trends
- Popular celestial objects
- Demographics (experience level, location)
- Estimated effort: 8-10 hours
-
Offline-First Sync
- Queue offline changes
- Batch sync when online
- Conflict resolution
- Service worker implementation
- Estimated effort: 12-16 hours
-
Localization (i18n)
- Support multiple languages
- Translations for UI
- Right-to-left language support
- Estimated effort: 8-10 hours
-
Dark/Light Mode Toggle
- CSS custom properties refactor
- Theme persistence
- System preference detection
- Estimated effort: 3-4 hours
- Create a feature branch:
git checkout -b feature/my-feature - Make changes incrementally
- Test thoroughly before committing
- Write clear commit messages
- Describe the changes clearly
- Reference related issues
- Include screenshots for UI changes
- Run tests before requesting review
- Follow existing code style
For issues, feature requests, or questions:
- Check existing GitHub issues
- Review this README first
- Open a detailed issue with reproduction steps
- Include browser/Node.js version info
[Add your license here - MIT recommended]
- Amateur astronomy community for inspiration
- NASA citizen science programs
- Chart.js and tsparticles libraries
- MongoDB and Express.js ecosystems
To run this project in production:
- Complete Priority 1 tasks (estimated 24-36 hours)
- Deploy backend to cloud (Heroku, Railway, DigitalOcean)
- Deploy frontend to CDN (Vercel, Netlify)
- Set up monitoring (error tracking, uptime monitoring)
- Plan marketing to astronomy communities
- Create social media presence
Built with LOVE for amateur astronomers and citizen scientists everywhere.
Last updated: September 1, 2026