{"id":45947793,"url":"https://github.com/miksrv/astronomy-portal","last_synced_at":"2026-05-09T01:18:51.909Z","repository":{"id":153286162,"uuid":"619941258","full_name":"miksrv/astronomy-portal","owner":"miksrv","description":"This project is intended for remote control of an amateur astronomical observatory. With the help of the WEB interface, you can control the power supply of the observatory devices, monitor the voltage, power current, as well as temperature and humidity in several places.","archived":false,"fork":false,"pushed_at":"2026-04-17T20:53:31.000Z","size":69937,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-17T22:40:24.532Z","etag":null,"topics":["astronomy","celestial","codeigniter","nextjs","observatory","php","react","redux","redux-toolkit","typescript"],"latest_commit_sha":null,"homepage":"https://astro.miksoft.pro","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/miksrv.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-03-27T18:04:31.000Z","updated_at":"2026-04-17T21:24:27.000Z","dependencies_parsed_at":"2023-12-03T19:24:10.777Z","dependency_job_id":"0728ad3c-8767-4aba-9c5c-e8953038eba8","html_url":"https://github.com/miksrv/astronomy-portal","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/miksrv/astronomy-portal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miksrv%2Fastronomy-portal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miksrv%2Fastronomy-portal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miksrv%2Fastronomy-portal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miksrv%2Fastronomy-portal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/miksrv","download_url":"https://codeload.github.com/miksrv/astronomy-portal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/miksrv%2Fastronomy-portal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32208477,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T03:15:14.334Z","status":"ssl_error","status_checked_at":"2026-04-24T03:15:11.608Z","response_time":64,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["astronomy","celestial","codeigniter","nextjs","observatory","php","react","redux","redux-toolkit","typescript"],"created_at":"2026-02-28T11:54:10.942Z","updated_at":"2026-04-24T04:00:54.309Z","avatar_url":"https://github.com/miksrv.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca id=\"top\"\u003e\u003c/a\u003e\n\nA web application for a DIY amateur observatory with support for remote monitoring, equipment management, weather data, and an astrophoto archive. Developed using PHP, MariaDB, Next.js, React, Redux RTK, SASS, and TypeScript. Please give the project a star :)\n\n\u003c!-- PROJECT TITLE --\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://miksoft.pro/images/observatory.webp\" alt=\"Homemade Observatory Web Application\" width=\"150\" height=\"150\"\u003e\n  \u003ch3\u003eHomemade Observatory Web Application\u003c/h3\u003e\n  \u003ca href=\"CHANGELOG.md\" target=\"_blank\"\u003eChangelog\u003c/a\u003e\n  ·\n  \u003ca href=\"https://astro.miksoft.pro\" target=\"_blank\"\u003eDemo\u003c/a\u003e\n  ·\n  \u003ca href=\"#contact\"\u003eContact\u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n\u003c!-- PROJECT BADGES --\u003e\n\u003cdiv align=\"center\"\u003e\n\n[![Contributors][contributors-badge]][contributors-url]\n[![Forks][forks-badge]][forks-url]\n[![Stargazers][stars-badge]][stars-url]\n[![Issues][issues-badge]][issues-url]\n[![MIT License][license-badge]][license-url]\n\n[![UI Checks](https://github.com/miksrv/astronomy-portal/actions/workflows/ui-checks.yml/badge.svg)](https://github.com/miksrv/astronomy-portal/actions/workflows/ui-checks.yml)\n[![UI Deploy](https://github.com/miksrv/astronomy-portal/actions/workflows/ui-deploy.yml/badge.svg)](https://github.com/miksrv/astronomy-portal/actions/workflows/ui-deploy.yml)\n[![API Deploy](https://github.com/miksrv/astronomy-portal/actions/workflows/api-deploy.yml/badge.svg)](https://github.com/miksrv/astronomy-portal/actions/workflows/api-deploy.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=miksrv_astronomy-portal\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=miksrv_astronomy-portal)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=miksrv_astronomy-portal\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=miksrv_astronomy-portal)\n\n\u003c/div\u003e\n\n---\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n### Table of Contents\n\n- [About the Project](#about-the-project)\n    - [Key Features](#key-features)\n    - [Built With](#built-with)\n- [Project Structure](#project-structure)\n- [Getting Started](#getting-started)\n    - [Prerequisites](#prerequisites)\n    - [Database](#database)\n    - [Backend Setup](#backend-setup)\n    - [Frontend Setup](#frontend-setup)\n- [Configuration](#configuration)\n    - [Frontend Environment Variables](#frontend-environment-variables)\n    - [Backend Environment Variables](#backend-environment-variables)\n- [API Overview](#api-overview)\n- [Deployment](#deployment)\n- [Contributing](#contributing)\n- [License](#license)\n- [Contact](#contact)\n\n---\n\n\u003c!-- ABOUT THE PROJECT --\u003e\n## About the Project\n\nAmateur Astronomy Observatory Portal is a DIY platform for managing and monitoring a remote observatory. The web app consists of several user screens, including displaying telemetry from the observatory, a weather station, storing processed astronomy photos, and storing information about captured frames. The app also features an interactive sky map, a deep sky image archive, and a live dashboard with weather and equipment statistics. The portal combines automation with practical astrophotography. Whether you are tracking celestial events or analyzing FITS footage, this project demonstrates the convergence of technology and astronomy.\n\n\u003c!-- KEY FEATURES --\u003e\n### Key Features\n\n- **Built with React and Next.js** — a fast and scalable web application for managing astronomical data.\n- **Interactive Celestial Map** — explore observed objects, constellations, stars, and their imaging history powered by Celestial.js and D3.js.\n- **Real-Time Observatory Dashboard** — monitor telescope status, weather conditions, and sensor data live.\n- **Astrophotography Archive** — FITS file management and astrophotography archive with detailed metadata, equipment info, and filters.\n- **Stargazing Events** — event management with registration, check-in via QR code, and photo upload.\n- **Astronomy Calculations** — visibility charts, celestial coordinate utilities, moon phase display using `astronomy-engine` and `suncalc`.\n- **Remote Observatory Control** — manage equipment power and receive telemetry via an Arduino-based controller.\n- **OAuth Authentication** — sign in with Google, Yandex, or VK accounts.\n- **Telegram Integration** — astronomy news and expedition reports synced with a Telegram channel.\n- **Multilingual UI** — i18n support via `i18next`.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n### Built With\n\nThe Homemade Observatory Web Application project leverages a wide range of technologies across various layers of the system:\n\n- [![PHP][php-badge]][php-url] Server-side scripting language (PHP 8.2) powering the CodeIgniter 4 backend API.\n- [![MySQL][mysql-badge]][mysql-url] MariaDB/MySQL database system for storing all application data.\n- [![JavaScript][js-badge]][js-url] Core language used in frontend development.\n- [![TypeScript][ts-badge]][ts-url] TypeScript extends JavaScript by adding types to the language (v5.9.3).\n- [![NextJS][nextjs-badge]][nextjs-url] React-based frontend framework for building the user interface (v16.1.6).\n- [![Redux][redux-badge]][redux-url] State management for the frontend via Redux Toolkit with RTK Query.\n- [![NodeJS][nodejs-badge]][nodejs-url] JavaScript runtime used for frontend development and package management (≥20.11.0).\n- [![Sass][sass-badge]][sass-url] Styling the user interface.\n- [![GitHub Actions][githubactions-badge]][githubactions-url] Continuous integration and deployment pipeline for automating tests and deployment processes.\n- [![SonarCloud][sonarcloud-badge]][sonarcloud-url] Code quality and security analysis.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n\u003c!-- PROJECT STRUCTURE --\u003e\n## Project Structure\n\nThis is a monorepo with three independent subsystems:\n\n```\nastronomy-portal/\n├── client/              # Next.js 16 frontend application\n│   ├── api/             # RTK Query API layer and data models\n│   ├── components/      # React UI components\n│   ├── pages/           # Next.js pages-router (routes)\n│   ├── public/          # Static assets, star map data, images\n│   └── utils/           # Utility functions (coordinates, dates, moon, etc.)\n├── server/              # CodeIgniter 4 PHP backend API\n│   └── app/\n│       ├── Controllers/ # Request handlers (Auth, Photos, Events, Objects…)\n│       ├── Models/      # Database models extending ApplicationBaseModel\n│       ├── Entities/    # DB row entity classes\n│       ├── Database/\n│       │   └── Migrations/ # Database migrations\n│       ├── Config/      # Routes, CORS, Filters, Services\n│       └── Libraries/   # JWT, Telegram, Locale helpers\n├── firmware/            # Arduino firmware for observatory hardware control\n│   └── main/\n└── config/              # Docker Compose and Nginx configuration\n```\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n\u003c!-- GETTING STARTED --\u003e\n## Getting Started\n\n### Prerequisites\n\n| Tool | Version |\n|------|---------|\n| Node.js | ≥ 20.11.0 |\n| Yarn | 4.9.2 |\n| PHP | ≥ 8.2 |\n| Composer | ≥ 2.x |\n| Docker \u0026 Docker Compose | any recent version |\n\n---\n\n### Database\n\nThe project uses MariaDB. Start a local instance via Docker Compose:\n\n```bash\ncd config\ndocker-compose up -d\n```\n\nThis starts a MariaDB 10.5.8 container accessible at `localhost:3308` with:\n- **Database:** `db`\n- **User:** `user`\n- **Password:** `password`\n\n---\n\n### Backend Setup\n\n```bash\ncd server\n\n# Install PHP dependencies\ncomposer install\n\n# Copy environment file and configure it\ncp .env.example .env\n\n# Run database migrations\ncomposer migration:run\n\n# (Optional) seed initial data\ncomposer seed:run\n\n# Start development server at http://localhost:8080\ncomposer serve\n```\n\n---\n\n### Frontend Setup\n\n```bash\ncd client\n\n# Install Node.js dependencies\nyarn install\n\n# Copy environment file and configure it\ncp .env.example .env\n\n# Start development server at http://localhost:3000\nyarn dev\n```\n\nTo build for production:\n\n```bash\nyarn build\n```\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n\u003c!-- CONFIGURATION --\u003e\n## Configuration\n\n### Frontend Environment Variables\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `NEXT_PUBLIC_SITE_LINK` | Public URL of the frontend | `http://localhost:3000/` |\n| `NEXT_PUBLIC_API_HOST` | Backend API base URL | `http://localhost:8080/` |\n| `NEXT_PUBLIC_IMG_HOST` | Base URL for serving uploaded images | `http://localhost:8080/` |\n| `NEXT_PUBLIC_LAT` | Observatory latitude (for sky map) | `51.7` |\n| `NEXT_PUBLIC_LON` | Observatory longitude (for sky map) | `55.2` |\n\n### Backend Environment Variables\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `CI_ENVIRONMENT` | App environment (`development` / `production`) | `development` |\n| `app.baseURL` | Backend base URL | `http://localhost:8080/` |\n| `app.appTimezone` | Server timezone | `Asia/Yekaterinburg` |\n| `app.latitude` | Observatory latitude | `51.7727` |\n| `app.longitude` | Observatory longitude | `55.0988` |\n| `app.fitsApiKey` | API key for FITS data source | — |\n| `app.telegramBotKey` | Telegram bot token | — |\n| `app.telegramChatID` | Telegram channel/chat ID | — |\n| `app.observatory.controller` | URL of Arduino relay controller | `http://astro.myftp.org:8081/` |\n| `app.observatory.webcam_1` | Webcam 1 snapshot URL | — |\n| `app.observatory.webcam_2` | Webcam 2 snapshot URL | — |\n| `auth.token.secret` | JWT secret key | — |\n| `auth.token.live` | JWT lifetime in seconds | `1209600` |\n| `auth.google.*` | Google OAuth credentials | — |\n| `auth.yandex.*` | Yandex OAuth credentials | — |\n| `auth.vk.*` | VK OAuth credentials | — |\n| `database.*.hostname` | DB host | `127.0.0.1` |\n| `database.*.port` | DB port | `3308` |\n| `database.*.database` | DB name | `db` |\n| `database.*.username` | DB user | `user` |\n| `database.*.password` | DB password | `password` |\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n\u003c!-- API OVERVIEW --\u003e\n## API Overview\n\nAll backend endpoints are defined in `server/app/Config/Routes.php`.\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `GET` | `/auth/me` | Current authenticated user info |\n| `GET` | `/auth/google` | OAuth via Google |\n| `GET` | `/auth/yandex` | OAuth via Yandex |\n| `GET` | `/auth/vk` | OAuth via VK |\n| `GET` | `/equipments` | Observatory equipment list |\n| `GET` | `/categories` | Photo categories list |\n| `GET\\|POST\\|PATCH\\|DELETE` | `/objects/:name` | Astronomical objects CRUD |\n| `GET` | `/fits/:name` | FITS file data for an object |\n| `GET\\|POST\\|PATCH\\|DELETE` | `/photos` | Astrophoto archive CRUD + upload |\n| `GET\\|POST\\|PATCH` | `/events` | Stargazing events management |\n| `POST` | `/events/booking` | Book a place at an event |\n| `POST` | `/events/cancel` | Cancel booking |\n| `POST` | `/events/checkin` | QR check-in |\n| `GET` | `/events/members` | Event member list |\n| `GET` | `/events/upcoming` | Upcoming events |\n| `GET` | `/relay/list` | Relay devices list |\n| `GET` | `/relay/light` | Observatory light status |\n| `PUT` | `/relay/set` | Set relay state |\n| `GET` | `/statistic/telescope` | Telescope usage statistics |\n| `GET` | `/files/:path` | File serving |\n| `GET` | `/sitemap` | Sitemap data |\n| `GET` | `/system/recalculate/fits` | Recalculate FITS filters |\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n\u003c!-- DEPLOYMENT --\u003e\n## Deployment\n\nCI/CD is handled by GitHub Actions (`.github/workflows/`):\n\n| Workflow | Trigger | Action |\n|----------|---------|--------|\n| `ui-checks.yml` | Pull Request | Lint + test + build frontend |\n| `ui-deploy.yml` | Push to `main` | Deploy frontend via SSH/rsync to VPS, served with PM2 |\n| `api-deploy.yml` | Push to `main` | Deploy backend via FTP to shared PHP hosting |\n| `sonarcloud.yml` | PRs + push to `main` | SonarCloud quality gate |\n\nThe frontend is built as a Next.js standalone app (`output: 'standalone'` in `next.config.js`) and managed by PM2 (`ecosystem.config.js`).\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n\u003c!-- CONTRIBUTING --\u003e\n## Contributing\n\nContributions are what make the open-source community an incredible environment for learning, inspiration, and innovation. Your contributions are highly valued and greatly appreciated, whether it's reporting bugs, suggesting improvements, or creating new features.\n\n**To contribute:**\n\n1. Fork the project by clicking the \"Fork\" button at the top of this page.\n2. Clone your fork locally:\n   ```bash\n   git clone https://github.com/miksrv/astronomy-portal.git\n   ```\n3. Create a new feature branch:\n   ```bash\n   git checkout -b feature/AmazingFeature\n   ```\n4. Make your changes, then commit them:\n   ```bash\n   git commit -m \"Add AmazingFeature\"\n   ```\n5. Push your changes to your forked repository:\n   ```bash\n   git push origin feature/AmazingFeature\n   ```\n6. Open a pull request from your feature branch to the main repository.\n\nWe encourage contributions of all kinds, whether big or small. Your efforts help improve the project for everyone!\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## License\n\n\u003c!-- LICENSE --\u003e\nDistributed under the MIT License. See [LICENSE](LICENSE) for more information.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n## Contact\n\nMisha - [miksoft.pro](https://miksoft.pro)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#top\"\u003eBack to top\u003c/a\u003e)\u003c/p\u003e\n\n---\n\n\u003c!-- MARKDOWN VARIABLES (LINKS, IMAGES) --\u003e\n[contributors-badge]: https://img.shields.io/github/contributors/miksrv/astronomy-portal.svg?style=for-the-badge\n[contributors-url]: https://github.com/miksrv/astronomy-portal/graphs/contributors\n[forks-badge]: https://img.shields.io/github/forks/miksrv/astronomy-portal.svg?style=for-the-badge\n[forks-url]: https://github.com/miksrv/astronomy-portal/network/members\n[stars-badge]: https://img.shields.io/github/stars/miksrv/astronomy-portal.svg?style=for-the-badge\n[stars-url]: https://github.com/miksrv/astronomy-portal/stargazers\n[issues-badge]: https://img.shields.io/github/issues/miksrv/astronomy-portal.svg?style=for-the-badge\n[issues-url]: https://github.com/miksrv/astronomy-portal/issues\n[license-badge]: https://img.shields.io/github/license/miksrv/astronomy-portal.svg?style=for-the-badge\n[license-url]: https://github.com/miksrv/astronomy-portal/blob/main/LICENSE.txt\n\n\u003c!-- Other ready-made icons can be seen for example here: https://github.com/inttter/md-badges --\u003e\n[js-badge]: https://img.shields.io/badge/JavaScript-F7DF1E?logo=javascript\u0026logoColor=000\n[js-url]: https://www.javascript.com/\n[ts-badge]: https://img.shields.io/badge/TypeScript-3178C6?logo=typescript\u0026logoColor=fff\n[ts-url]: https://www.typescriptlang.org/\n[nextjs-badge]: https://img.shields.io/badge/Next.js-black?logo=next.js\u0026logoColor=white\n[nextjs-url]: https://nextjs.org/\n[nodejs-badge]: https://img.shields.io/badge/Node.js-6DA55F?logo=node.js\u0026logoColor=white\n[nodejs-url]: https://nodejs.org/\n[redux-badge]: https://img.shields.io/badge/Redux-764ABC?logo=redux\u0026logoColor=fff\n[redux-url]: https://redux.js.org/\n[sass-badge]: https://img.shields.io/badge/Sass-C69?logo=sass\u0026logoColor=fff\n[sass-url]: https://sass-lang.com/\n[php-badge]: https://img.shields.io/badge/php-%23777BB4.svg?\u0026logo=php\u0026logoColor=white\n[php-url]: https://www.php.net/\n[mysql-badge]: https://img.shields.io/badge/MySQL-4479A1?logo=mysql\u0026logoColor=fff\n[mysql-url]: https://www.mysql.com/\n[sonarcloud-badge]: https://img.shields.io/badge/SonarCloud-F3702A?logo=sonarcloud\u0026logoColor=fff\n[sonarcloud-url]: https://sonarcloud.io/\n[githubactions-badge]: https://img.shields.io/badge/GitHub_Actions-2088FF?logo=github-actions\u0026logoColor=white\n[githubactions-url]: https://docs.github.com/en/actions\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiksrv%2Fastronomy-portal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmiksrv%2Fastronomy-portal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiksrv%2Fastronomy-portal/lists"}