PROJECT OVERVIEW:
The application, named 'SkyWatch', is a comprehensive SaaS platform designed for amateur and professional astronomers, astronomy clubs, and science enthusiasts. It aims to capture, analyze, and share celestial events like meteor showers and fireballs. The core value proposition lies in providing a unified, real-time network of sky-monitoring cameras, offering live feeds, a searchable archive of spectacular events, and detailed information about network stations. It addresses the problem of fragmented and inaccessible data regarding celestial phenomena, making advanced observation tools accessible to a wider audience. SkyWatch will not just be a display tool but a collaborative platform, enabling users to contribute to a larger astronomical dataset.
TECH STACK:
- Frontend: React (Next.js App Router)
- Styling: Tailwind CSS
- Backend Framework: Next.js API Routes (or a separate Node.js/Express.js server)
- Database: PostgreSQL with Drizzle ORM
- Authentication: NextAuth.js (or Clerk for a simpler setup)
- UI Components: shadcn/ui
- State Management: Zustand or React Context API
- Data Fetching: React Query (or SWR)
- Charting (Optional for MVP but good for future): Chart.js or Recharts
- Deployment: Vercel or a similar platform
- Essential Packages: `next`, `react`, `react-dom`, `tailwindcss`, `drizzle-orm/pg-core`, `drizzle-orm/client`, `postgres`, `next-auth`, `shadcn-ui`, `zustand`, `react-query`, `date-fns`, `clsx`
DATABASE SCHEMA:
Primary Tables:
1. `users`:
- `id`: UUID (Primary Key)
- `name`: VARCHAR
- `email`: VARCHAR (Unique)
- `emailVerified`: TIMESTAMP
- `image`: VARCHAR (URL for profile picture)
- `createdAt`: TIMESTAMP (default now())
- `updatedAt`: TIMESTAMP
2. `accounts` (for NextAuth.js):
- `id`: BIGSERIAL (Primary Key)
- `userId`: UUID (Foreign Key to users.id)
- `type`: VARCHAR (e.g., 'oauth', 'email')
- `provider`: VARCHAR
- `providerAccountId`: VARCHAR
- `refresh_token`: TEXT
- `access_token`: TEXT
- `expires_at`: BIGINT
- `token_type`: VARCHAR
- `scope`: VARCHAR
- `id_token`: TEXT
- `session_state`: VARCHAR
3. `sessions` (for NextAuth.js):
- `sessionToken`: VARCHAR (Primary Key)
- `userId`: UUID (Foreign Key to users.id)
- `expires`: TIMESTAMP
4. `verificationTokens` (for NextAuth.js):
- `identifier`: VARCHAR (Primary Key)
- `token`: VARCHAR (Unique)
- `expires`: TIMESTAMP
5. `cameraStations`:
- `id`: UUID (Primary Key, default gen_random_uuid())
- `name`: VARCHAR (e.g., 'Istanbul Station 1')
- `locationDescription`: VARCHAR (e.g., 'Bosphorus Observatory')
- `latitude`: DECIMAL(9, 6)
- `longitude`: DECIMAL(9, 6)
- `altitude`: INTEGER
- `status`: VARCHAR (e.g., 'Online', 'Offline', 'Maintenance')
- `lastHeartbeat`: TIMESTAMP
- `ownerId`: UUID (Foreign Key to users.id, nullable for public stations)
- `createdAt`: TIMESTAMP (default now())
- `updatedAt`: TIMESTAMP
6. `cameras`:
- `id`: UUID (Primary Key, default gen_random_uuid())
- `stationId`: UUID (Foreign Key to cameraStations.id)
- `model`: VARCHAR (e.g., 'AllSky7 Unit')
- `sensor`: VARCHAR (e.g., 'SONY STARVIS IMX291')
- `lens`: VARCHAR (e.g., '4mm f/1.0')
- `fps`: INTEGER (e.g., 25)
- `fieldOfView`: VARCHAR (e.g., '45x80 degrees')
- `orientation`: VARCHAR (e.g., 'Horizon', 'North 70deg', 'South 70deg')
- `isRecording`: BOOLEAN (default true)
- `createdAt`: TIMESTAMP (default now())
- `updatedAt`: TIMESTAMP
7. `recordings`:
- `id`: UUID (Primary Key, default gen_random_uuid())
- `stationId`: UUID (Foreign Key to cameraStations.id)
- `cameraIds`: UUID[] (Array of camera IDs that captured this event)
- `eventType`: VARCHAR (e.g., 'Fireball', 'Meteor Shower', 'Other Interesting Event')
- `eventTimestamp`: TIMESTAMP
- `durationSeconds`: FLOAT
- `description`: TEXT (User-submitted or AI-generated description)
- `thumbnailUrl`: VARCHAR (URL to a preview image)
- `videoUrl`: VARCHAR (URL to the full video, potentially stored externally like S3)
- `isPublic`: BOOLEAN (default true)
- `recordedAt`: TIMESTAMP (default now())
8. `weatherData`:
- `id`: UUID (Primary Key, default gen_random_uuid())
- `stationId`: UUID (Foreign Key to cameraStations.id)
- `timestamp`: TIMESTAMP
- `temperature`: DECIMAL(5, 2)
- `humidity`: DECIMAL(5, 2)
- `windSpeed`: DECIMAL(5, 2)
- `windDirection`: VARCHAR
- `precipitation`: VARCHAR
- `cloudCover`: VARCHAR
- `notes`: TEXT (e.g., 'Clear skies', 'Light rain')
CORE FEATURES & USER FLOW:
1. Authentication:
- Flow: User lands on the homepage. Clicks 'Sign In/Sign Up'. Redirected to auth provider (e.g., Google, Email/Password). After successful auth, redirected to the dashboard.
- Edge Cases: Handling OAuth callbacks, email verification, password reset, session expiration.
2. Dashboard Overview:
- Flow: Authenticated users land here. Displays a summary of recent events, network status (online/offline stations), and quick links to live view and archive.
- User Action: Click on 'Network Status' or 'Live View'.
- Edge Cases: Empty state (no recent events), loading states, error handling.
3. Network Status & Station Details:
- Flow: User navigates to the 'Network Status' page. A map displays icons for each camera station. Clicking an icon opens a modal or sidebar with details: station name, location (lat/lon/alt), current status (Online/Offline/Maintenance), last heartbeat time, associated cameras, and recent recordings from that station. Weather data is also displayed here.
- User Action: Click station icon. View details. Potentially click 'View Live Feed' from here.
- Edge Cases: Station offline, no weather data available, no cameras associated.
4. Live View:
- Flow: User navigates to the 'Live View' page. A grid or list displays active camera feeds. Each feed updates every 15 minutes. Users can click on a feed to view it in a larger modal or dedicated view.
- User Action: Browse live feeds. Select a feed for a closer look.
- Edge Cases: Camera offline, feed not updating, stream errors, limited concurrent viewers (if applicable).
5. Fireball Archive:
- Flow: User navigates to the 'Fireball Archive'. A browsable, filterable list/gallery of recorded spectacular fireballs is shown. Each entry displays a thumbnail, event type ('Fireball'), timestamp, brief description, and station(s) involved. Clicking an entry opens a detailed view with the video, more information, and related weather data.
- User Action: Browse, filter (by date, location, event type), select an event for details.
- Edge Cases: Empty archive, filters returning no results, video playback errors, missing data.
6. Other Events:
- Flow: Similar to Fireball Archive, but for 'Other Interesting Events'. Allows users to discover less common but still notable celestial recordings.
- User Action: Browse and view details.
- Edge Cases: Similar to Fireball Archive.
7. Camera Station Management (Future MVP or v1.1):
- Flow: Users (with appropriate permissions, e.g., station owners) can add new stations, edit existing ones, and manage their associated cameras.
- User Action: Add Station Form, Edit Station Form.
- Edge Cases: Invalid location data, duplicate station names, camera configuration errors.
API & DATA FETCHING:
- API Routes (Next.js App Router `app/api/...` or Route Handlers in `app/api/.../route.ts`):
- `GET /api/stations`: Fetch list of all camera stations (public data).
- `GET /api/stations/[id]`: Fetch details for a specific station, including its cameras and recent weather data.
- `GET /api/stations/[id]/cameras`: Fetch cameras associated with a station.
- `GET /api/stations/[id]/weather`: Fetch current/recent weather for a station.
- `GET /api/recordings`: Fetch a list of recordings (fireballs, other events), with filtering and pagination.
- `GET /api/recordings/[id]`: Fetch details for a specific recording.
- `GET /api/live/feeds`: Fetch URLs/status for current live camera feeds.
- `POST /api/auth/signup`, `POST /api/auth/signin`: Handled by NextAuth.js.
- `POST /api/stations`: Create a new station (requires auth).
- `PUT /api/stations/[id]`: Update a station (requires auth).
- Data Fetching Strategy:
- Server Components for initial page loads and SEO (fetching station lists, recording archives).
- Client Components using React Query/SWR for dynamic data, interactive elements (live feed status, map markers, filters, form submissions).
- API responses will be JSON.
- Example Request (`GET /api/stations`): No body.
- Example Response (`GET /api/stations`):
```json
[
{
"id": "uuid-station-1",
"name": "Istanbul Station 1",
"latitude": 41.01,
"longitude": 29.02,
"status": "Online",
"lastHeartbeat": "2023-10-27T10:00:00Z"
},
// ... more stations
]
```
COMPONENT BREAKDOWN (Next.js App Router):
- `app/layout.tsx`: Root layout (HTML, Head, Body, global providers, Tailwind CSS setup).
- `app/page.tsx`: Landing Page (Public, features overview, call to action).
- `app/(auth)/signin/page.tsx`: Sign In page.
- `app/(auth)/signup/page.tsx`: Sign Up page.
- `app/dashboard/page.tsx`: (Protected) User dashboard. Summary cards for recent events, network health.
- `app/network/page.tsx`: (Protected) Network Status. Interactive map of stations.
- `app/network/[stationId]/page.tsx`: (Protected) Individual Station Detail page. Shows station info, cameras, weather.
- `app/live/page.tsx`: (Protected) Live View page. Grid of camera feeds.
- `app/archive/page.tsx`: (Protected) Fireball Archive. Filterable list/gallery of recordings.
- `app/archive/[recordingId]/page.tsx`: (Protected) Individual Recording Detail page.
- `app/other-events/page.tsx`: (Protected) Other Events Archive.
- `app/other-events/[recordingId]/page.tsx`: (Protected) Individual Event Detail page.
- `app/settings/page.tsx`: (Protected) User Profile & Settings.
- `app/api/...`: API Routes/Route Handlers.
UI Components (using shadcn/ui):
- `components/ui/button`: For actions (Sign In, View Details, Filter).
- `components/ui/card`: For displaying event summaries, station info.
- `components/ui/table`: For detailed event lists, possibly weather logs.
- `components/ui/map`: (Custom or using a library like Leaflet/Mapbox GL JS integrated with React) To display station locations.
- `components/ui/modal`: For detailed views of cameras or event information.
- `components/ui/input`, `components/ui/label`, `components/ui/form`: For settings and potential future station management forms.
- `components/ui/skeleton`: For loading states.
- `components/ui/alert`, `components/ui/alert-dialog`: For error messages and confirmations.
- `components/ui/dropdown-menu`, `components/ui/select`: For filtering and sorting options.
- `components/Navbar`: Main navigation (conditional rendering for auth status).
- `components/Footer`: Standard footer.
- `components/StationMarker`: Custom map marker component.
- `components/CameraFeed`: Component to display a single live or recorded feed.
- `components/EventCard`: Component for archive listings.
State Management: Primarily server/client component data fetching. Local state within components for UI interactions. Global state (Zustand) for shared states like user authentication status or theme.
UI/UX DESIGN & VISUAL IDENTITY:
- Design Style: "Modern Minimalist Clean" with subtle astronomical elements.
- Color Palette:
- Primary: Dark Blue/Navy (`#1A203C`)
- Secondary: Deep Space Black (`#0B0E1A`)
- Accent: Vibrant Cyan/Teal (`#00FFFF` or `#4FD1C5`)
- Highlight/Call to Action: Bright White/Light Gray (`#F7FAFC`)
- Subtle Accents: Muted Purple (`#6B46C1`)
- Typography:
- Headings: Sans-serif, modern, slightly wide. (e.g., 'Inter' or 'Exo 2')
- Body Text: Highly readable sans-serif. (e.g., 'Inter' or 'Roboto')
- Layout: Clean, spacious layouts. Card-based design for summaries. Full-width sections for immersive views (live feeds, maps). Sidebar or modal for details.
- Responsiveness: Mobile-first approach. Adapts gracefully to tablet and desktop screens. Navigation collapses into a hamburger menu on smaller screens. Map interaction optimized for touch.
- Visual Elements: Subtle background gradients mimicking nebulae or star fields. Clean icons. Possibly animated stars or light trails in loading states.
ANIMATIONS:
- Page Transitions: Smooth fade or slide transitions using Next.js `AnimatePresence` (if using Framer Motion).
- Hover Effects: Subtle scaling or background color changes on interactive elements (buttons, cards).
- Loading States: Skeleton loaders or subtle pulsing/shimmering animations for data fetching.
- Map Interactions: Smooth zooming and panning.
- Micro-interactions: Button press feedback, subtle animations on status changes.
EDGE CASES:
- Authentication: Handle guest users (viewing public data) vs. logged-in users (accessing protected areas). Implement robust session management.
- Empty States: Design clear and informative empty states for dashboards, archives, or station lists when no data is available (e.g., "No fireballs recorded yet. Check back later!").
- Data Loading: Implement global loading indicators and individual component loaders.
- Error Handling: Graceful error display (e.g., toast notifications, error message banners) for API failures, invalid data, or permission issues. Implement retry mechanisms where appropriate.
- Validation: Client-side and server-side validation for all user inputs (e.g., station details, search filters).
- Permissions: Ensure only authenticated users can access certain features (e.g., settings, creating stations).
- API Rate Limiting: Implement if necessary to prevent abuse.
- No Camera Data: Handle cases where a station is online but its specific camera feeds are unavailable.
SAMPLE DATA:
1. `stations` Table:
- `id`: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
`name`: "Ankara Observatory"
`latitude`: 39.93
`longitude`: 32.86
`status`: "Online"
`lastHeartbeat`: "2023-10-27T14:30:00Z"
- `id`: "b8a7b3c1-9d8e-4f5a-8c7d-6e5f4a3b2c1d"
`name`: "Izmir Coastal Watch"
`latitude`: 38.42
`longitude`: 27.14
`status`: "Maintenance"
`lastHeartbeat`: "2023-10-26T08:00:00Z"
2. `cameras` Table:
- `id`: "c1a2b3d4-e5f6-7890-1234-567890abcdef"
`stationId`: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
`model`: "AllSky7 Unit"
`sensor`: "SONY STARVIS IMX291"
`orientation`: "Horizon"
- `id`: "d2b3c4e5-f6a7-8901-2345-67890abcdef0"
`stationId`: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
`model`: "AllSky7 Unit"
`sensor`: "SONY STARVIS IMX291"
`orientation`: "North 70deg"
3. `recordings` Table:
- `id`: "e3d4c5b6-a7b8-9012-3456-7890abcdef01"
`stationId`: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
`cameraIds`: ["c1a2b3d4-e5f6-7890-1234-567890abcdef"]
`eventType`: "Fireball"
`eventTimestamp`: "2023-10-25T22:15:05Z"
`durationSeconds`: 3.5
`description`: "Bright green fireball entering from the east."
`thumbnailUrl`: "/thumbnails/fireball_20231025_221505.jpg"
`videoUrl`: "/videos/fireball_20231025_221505.mp4"
- `id`: "f4e5d6c7-b8a9-0123-4567-890abcdef012"
`stationId`: "b8a7b3c1-9d8e-4f5a-8c7d-6e5f4a3b2c1d"
`cameraIds`: ["d2b3c4e5-f6a7-8901-2345-67890abcdef0"]
`eventType`: "Other Interesting Event"
`eventTimestamp`: "2023-10-24T03:05:10Z"
`durationSeconds`: 1.2
`description`: "Unusual atmospheric glow detected near zenith."
`thumbnailUrl`: "/thumbnails/glow_20231024_030510.jpg"
`videoUrl`: "/videos/glow_20231024_030510.mp4"
4. `weatherData` Table:
- `id`: "01234567-89ab-cdef-0123-456789abcdef"
`stationId`: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
`timestamp`: "2023-10-27T14:35:00Z"
`temperature`: 15.5
`humidity`: 65.2
`windSpeed`: 5.1
`windDirection`: "SW"
`cloudCover`: "Partly Cloudy"
`notes`: ""
5. `users` Table:
- `id`: "a1b2c3d4-e5f6-7890-1234-567890abcdef"
`name`: "Alice Astronomy"
`email`: "alice@example.com"
`image`: "/images/avatars/alice.png"
TURKISH TRANSLATIONS:
- Sign In: 'Giriş Yap'
- Sign Up: 'Kayıt Ol'
- Dashboard: 'Kontrol Paneli'
- Network Status: 'Ağ Durumu'
- Live View: 'Canlı Görüntü'
- Archive: 'Arşiv'
- Settings: 'Ayarlar'
- Station Name: 'İstasyon Adı'
- Location: 'Konum'
- Status: 'Durum'
- Last Heartbeat: 'Son Nabız'
- Weather: 'Hava Durumu'
- Temperature: 'Sıcaklık'
- Humidity: 'Nem'
- Wind Speed: 'Rüzgar Hızı'
- Event Type: 'Olay Türü'
- Timestamp: 'Zaman Damgası'
- Description: 'Açıklama'
- View Details: 'Detayları Gör'
- Filter: 'Filtrele'
- Search: 'Ara'
- No Data Available: 'Veri Mevcut Değil'
- Loading...: 'Yükleniyor...'
- Error: 'Hata'
- Recordings: 'Kayıtlar'
- Cameras: 'Kameralar'
- Camera Stations: 'Kamera İstasyonları'
- Fireball Archive: 'Ateş Topu Arşivi'
- Other Events: 'Diğer Olaylar'