Advanced satellite tracking and pass prediction system with intelligent filtering and horizon masking
A satellite tracking application that provides pass predictions for multiple ground stations with real-world visibility calculations based on actual horizon obstacles.
If you are here just to run the project, refer to the Quick Start (deployment) section below.
Traditional satellite tracking tools often fall short in these key areas:
- Advanced Filtering: Quickly filter thousands of satellites by custom lists or specific transmitter frequency bands
- Time-Based Pass Filtering: Find passes during specific times of day or days of week that fit your schedule
- Real-World Visibility: Account for actual horizon obstacles (buildings, trees, mountains) at your observation station, not just theoretical calculations
- High-Value Pass Extraction: Automatically identify and extract "high-value" passes based on your criteria and sync them to your calendar
- Accurate Pass Properties: Get visibility duration and maximum elevation based on actual pass visibility, considering your local horizon mask
- Multi-criteria Search: Filter by satellite name, NORAD ID, custom tags, or frequency bands
- Frequency Band Filtering: Support for multiple frequency ranges with uplink/downlink direction
- Tag Management: Organize satellites with custom tags (Amateur, METEOR, Orbcomm, YourTag, etc.)
- Tracked Satellites: Mark and filter your favorite satellites for quick access
- Multiple Stations: Manage unlimited observation locations
- Horizon Mask Editor: Interactive polar plot editor to mark obstacles
- Geographic Visualization: Interactive maps with geodesic lines and satellite footprints. Real-time visualization of satellite positions and paths
- Orbit-Based Predictions: Calculate passes for specific satellites over multiple days
- Visibility Segmentation: Split passes into visible segments based on horizon masks
- Pass Comparison: Compare the same orbital pass across different ground stations
- Time Filtering: Filter passes by time of day and day of week with ability to combine multiple filters
- Live Satellite Position: Real-time position updates with Doppler shift calculations
- Pass Progress: Visual progress indicators for ongoing passes
- Sky Charts: Polar plot visualization showing current satellite position and predicted path
- Automatic TLE Updates: Configurable TLE sources with automatic refresh
- SatNOGS DB Integration: Import transmitter data and satellite information
- Backend: NestJS 11.x (TypeScript, Node.js), PostgreSQL 18 with Prisma ORM, satellite.js, tle.js, Swagger
- Frontend: React 19.x with TypeScript, Vite 7.x, Zustand, React Query, Orval, Lucide icons, Leaflet, SCSS
Note: This guide assumes a development environment setup. Proper docker images for non-developer audience coming soon.
- Docker and Docker Compose
- Node.js 20+ and npm
- Git
-
Clone the repository
git clone https://github.com/ivan.petrushev/my-watch-tower.git cd my-watch-tower -
Start infrastructure services
docker compose up -d postgres redis pgadmin
This starts PostgreSQL, pgAdmin (optional), and Redis (for BullMq).
-
Install dependencies
cd backend && npm install cd ../frontend && npm install
-
Configure environment
Copy
backend/.env.sampletobackend/.envprobably no need to adjust anything. -
Run database migrations
cd backend npx prisma migrate deploy npx prisma generate -
Start development servers
Start separately:
# Terminal 1 - Backend
cd backend
npm run dev
# Terminal 2 - Frontend
cd frontend
npm run dev-
Access the application
- Frontend: http://localhost:5173
- API Docs: http://localhost:3000/api/swagger
- pgAdmin: http://localhost:8080 (admin@example.com / admin123)
cd backend
# Start dev server with hot reload
npm run dev
# Run database migrations after schema change
npx prisma migrate dev --name migration_name
# Generate Prisma client after schema changes
npx prisma generate
# View database in Prisma Studio
npx prisma studiocd frontend
# Start dev server
npm run dev
# Regenerate API client after backend changes
npm run orval
pgAdmin is available at http://localhost:8080
Default credentials:
- Email: admin@example.com
- Password: admin123
Server connection is pre-configured in docker-confs/pgadmin-servers.json.
Docker Compose is used for easy deployment. Refer to Quick Start (development) for local dev setup.
-
Start the containers
Run
docker compose up -dto run all the services - backend, frontend, Redis, PostgreSQL, pgAdmin (optional), nginx. First startup may take a while as it downloads all needed SatNOGS resources. Docker images are set tolatesttag, but if you want to run stable versions, you can check specific tag from GitHub. Migrations will be applied automatically via thebackend-migrateservice.If you prefer to run the migrations manually, you can run the rest of the services separately.
docker compose up -d redis postgres docker compose up backend-migrate docker compose up -d redis postgres backend frontend nginx
-
Access the application
- Frontend: http://localhost
- API Docs: http://localhost/api/swagger
- pgAdmin: http://localhost:8080 (credentials admin@example.com / admin123)
My Watch Tower supports exporting pass predictions to calendar applications through standard iCalendar (ICS) format. This enables automatic synchronization of satellite passes with your preferred calendar service.
Calendar feeds are generated dynamically based on your Filter Presets and Ground Stations:
- One feed per combination: Each calendar subscription represents a specific Filter Preset applied to a specific Ground Station
- Dynamic updates: Feeds reflect the current state of calculated pass events
- Multiple feeds: Create separate subscriptions for different filter criteria or observation locations
For external calendar services to access your ICS endpoints, the backend API must be publicly accessible:
- Local Network: Configure port forwarding (DNAT) on your router to expose port 3000
- Alternative Solutions: Use reverse proxy services like ngrok, Cloudflare Tunnel, or similar
- Public Address: Note your public-facing URL (e.g.,
https://your-domain.comorhttp://your-ip:3000)
- Navigate to Filter Presets in the application
- Enter your Public Address in the configuration field
- Save the configuration
This address is used to generate absolute URLs for calendar subscription links.
For each Filter Preset and Ground Station combination, you have two options:
A) Manual Export
- Click Export to download an ICS file
- Import the file into your calendar application
- Note: This is a one-time snapshot; updates require re-exporting
B) Dynamic Subscription (Recommended)
- Copy the iCal Link URL
- Add as a calendar subscription in your application
- The feed automatically updates as pass predictions change
- Requires your backend to be publicly accessible
<Ground Station Name> / <Filter Preset Name>
- Title: Satellite name
- Time: Pass visibility window (AOS to LOS)
- Location: Ground Station name and coordinates
- Description:
- Satellite name
- Maximum elevation (degrees)
- Total visible duration (seconds)
- Google Calendar: Add other calendars > From URL
- Apple Calendar: TBD
- Outlook: TBD
- Thunderbird: TBD
- Timeline view: Visualize upcoming passes in a timeline format
- Current sky: Real-time sky chart with all visible satellites
- Production Docker Images: Create optimized Docker images for backend and frontend
- Complete Docker Compose: Production-ready compose file with all services
- Calendar Integration: Sync high-value passes to Google Calendar/iCal
- Satellite info page: Detailed satellite information, transmitter list and citations
- Pass Logging: Ability to log observations and attach media
- Weather Integration: Filter passes by weather conditions
- Satellite custom tags: Ability to assign cutom tags to satellite for filtering
- Filter saving: Save and load custom filter presets
- Tests: Both backend and frontend need tests
- Pass Statistics: Historical pass analytics
- Multi-language Support: i18n implementation
- News aggregation: Aggregating news for tracked satellites from several sources
- CI/CD Pipeline: GitHub Actions for testing and deployment
- Backup Strategy: Automated database backups
- Performance Testing: Load testing and optimization
No need to change this, if you are running the provided docker-compose.yml.
# Database
DATABASE_URL="postgresql://admin:admin123@localhost:5432/my_watch_tower"
REDIS_HOST=localhost
REDIS_PORT=6379(No .env variables, as getting ENV to work in Vite + Docker is a bit tricky)
This project is currently in active development (WIP). Contributions, issues, and feature requests are welcome!
- Follow existing code style and patterns
- Write meaningful commit messages
- Update documentation for new features
- Add tests for new functionality
- Run linters before committing
This project is licensed under the MIT license - see the LICENSE file for details.
- Claude 4.5 and Gemini 3 Pro - AI assistance is just a tool for building a better product. It is every developer's responsibility to use it ethically and effectively.
- SatNOGS - Satellite and transmitter database, TLE data sources
- satellite.js - SGP4 propagation library
- TLE.js - TLE parsing and analysis
- Leaflet & leaflet.geodesic - Interactive mapping
Status: 🚧 Work in Progress - Active Development
Built with ❤️ for the satellite tracking community


