Features • Live Demo • Screenshots • Tech Stack • Getting Started • Development • Environment Variables • License
NinerWatch is a real-time campus safety monitoring platform for UNC Charlotte students, faculty, and community members. It aggregates, visualizes, and provides a discussion platform for campus police reports and safety incidents.
🚨 DISCLAIMER: NinerWatch is not affiliated with or endorsed by UNC Charlotte. This is an unofficial service created to aggregate and display publicly available campus safety information.
🗺️ Interactive Campus Map - Visualize incident locations across campus
📊 Safety Statistics - Analyze trends and patterns in campus safety data
💬 Community Discussion - Anonymous commenting on incident reports
🔔 Live News Ticker - Latest campus safety news and alerts
📱 Mobile Responsive - Access on any device with a responsive UI
🕒 Real-time Updates - Automatically refreshes with new incident data
📈 Analytics Dashboard - Visual breakdowns of incident categories and hotspots
📑 Detailed Incident Reports - Comprehensive information for each event
🌙 Dark Mode - Eye-friendly dark theme for better night viewing
Visit the live demo at https://ninerwatch.org/
- Frontend: Next.js 15, React 19, TypeScript
- Styling: Tailwind CSS, shadcn/ui
- Database: Supabase (Postgres)
- Maps: Leaflet, React Leaflet
- Data Processing: GitHub Actions, Python
- Deployment: Vercel
- Node.js 20+
- bun, pnpm, npm, or yarn
- A Supabase account
-
Clone the repository
git clone https://github.com/yourusername/ninerwatch.git cd ninerwatch -
Install dependencies
bun install # or pnpm install # or npm install # or yarn install
-
Set up environment variables (see Environment Variables)
-
Run the development server
bun run dev # or pnpm run dev # or npm run dev # or yarn dev
-
Open http://localhost:3000 with your browser to see the result
├── .github/ # GitHub Actions workflows
├── public/ # Static files
├── scripts/ # Python scripts for data processing
├── src/
│ ├── app/ # Next.js App Router
│ ├── components/ # React components
│ │ ├── dashboard/ # Dashboard-specific components
│ │ ├── map/ # Map-related components
│ │ └── ui/ # UI components
│ ├── context/ # React context providers
│ └── lib/ # Utility functions and API clients
- GitHub Actions run on an hourly schedule to fetch new police logs
- Python scripts parse PDF files and extract incident information
- Data is stored in Supabase database
- Next.js frontend retrieves and displays the data in real-time
Create a .env file in the root directory with the following variables:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_keyThe application requires two main tables:
id(uuid, primary key)report_number(text)incident_type(text)incident_location(text)date_reported(date)time_reported(timestamp)time_secured(timestamp, nullable)time_of_occurrence(timestamp, nullable)disposition(text, nullable)incident_description(text, nullable)created_at(timestamp, default: now())
id(uuid, primary key)incident_id(uuid, foreign key to crime_incidents.id)parent_id(uuid, nullable, self-referential)reply_to_id(uuid, nullable)comment_text(text)user_color(text)votes(integer, default: 0)created_at(timestamp, default: now())
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/new-feature) - Commit your changes (
git commit -m 'Add new feature') - Push to the branch (
git push origin feature/new-feature) - Open a Pull Request
This project is licensed under the CC Attribution-NonCommercial-ShareAlike 4.0 International License - see the LICENSE file for details.
- Data source: UNC Charlotte Police Department
- Map tiles: CartoDB
- Icons from Lucide
- UI components based on shadcn/ui


