ScreenNet: Turning Dead Screens Into Living Communication
Team Members
- John Song
- Rishith Auluka
- Hiep Pham
Inspiration
Walk through any UGA library or student center and you'll notice screens -- big, bright, and doing absolutely nothing. Meanwhile, student organizations are stuck fighting for attention on Instagram stories that vanish in 24 hours. We saw a disconnect: unused infrastructure on one side, unmet communication needs on the other.
The problem wasn't a lack of technology. UGA already has dozens of digital displays scattered across campus. The problem was fragmentation. No centralized system. Content uploaded via USB drives. No approval workflow. No analytics. No way to push an emergency alert to every screen simultaneously.
ScreenNet was born from that gap -- the realization that the biggest impact wouldn't come from installing more screens, but from connecting the ones that already exist.
What It Does
Purpose: ScreenNet solves the campus communication gap by connecting underutilized digital displays into a unified network. Student organizations struggle to reach their audience through ephemeral social media posts, while dozens of campus screens sit idle or display outdated content. ScreenNet bridges this disconnect by providing a centralized platform where student orgs can submit campaign content, administrators can approve and manage what gets displayed, and physical screens automatically show relevant, timely information to the campus community.
ScreenNet is a three-layer platform that turns scattered displays into a managed communication network:
Admin Dashboard (The Nerve Center)
Real-time monitoring with live heartbeat tracking for every screen (green = online, gray = offline, amber = maintenance). Campaign management lets you create, schedule, and prioritize content with automatic expiration. Content governance happens through a streamlined approval queue -- we're targeting under 30 seconds per review. The analytics engine tracks impressions, screen utilization, and content performance with CSV export for university reporting.
Student Organization Portal
Student orgs can submit campaign requests for events, promotions, and announcements. They can target specific buildings or campus zones, set priority levels and date ranges, and track their approval status in real-time.
Display Client (The Physical Screens)
This is a lightweight web app running on any display hardware. The priority-weighted scheduler ensures urgent content like safety alerts appears more frequently while normal content gets fair rotation. We built it offline-first -- service workers cache content locally so WiFi drops don't mean blank screens. The heartbeat system pings our backend every 30 seconds to report health status.
Key Feature: UGA Calendar Sync
Official university events auto-import from the central calendar, so the platform feeds itself with authoritative content.
How We Built It
We approached this as a design-first engineering problem, starting with a comprehensive spec document before writing application code.
The architecture breaks down into three layers. The frontend layer uses React 19, TypeScript, and TailwindCSS -- we have an admin dashboard at localhost:5173 and the display client at localhost:5174. The backend layer runs Hono with PostgreSQL and Drizzle ORM, handling the REST API for campaign CRUD and approval workflow, Server-Sent Events for real-time screen updates, and a heartbeat monitor that tracks display client health. The data layer is PostgreSQL storing campaigns, screens, impressions, and the approval queue, with shared Zod schemas giving us end-to-end type safety.
Tech Stack:
- Monorepo: pnpm + Turborepo for shared code reuse
- Frontend: React 19, TypeScript, TailwindCSS (white-primary, blue-accent design system), Framer Motion for transitions, Recharts for analytics
- Backend: Hono (Node.js), PostgreSQL, Drizzle ORM
- Real-time Updates: Server-Sent Events for push notifications to display clients
- Offline Resilience: Service workers cache content on display clients -- if WiFi drops, screens show last known state
- Type Safety: Shared Zod schemas across frontend/backend prevent runtime errors
Third-Party Frameworks & APIs:
- React (Meta) - UI component library
- TailwindCSS (Tailwind Labs) - Utility-first CSS framework
- Framer Motion (Framer) - Animation library for React
- Recharts (Recharts) - Charting library built on React and D3
- Hono - Lightweight web framework for Node.js
- PostgreSQL - Open-source relational database
- Drizzle ORM - TypeScript ORM for type-safe database queries
- Zod - TypeScript-first schema validation library
- Turborepo (Vercel) - High-performance build system for monorepos
- Vite - Fast build tool and dev server
We optimized for three user personas: admins need speed (30-second review target) and visibility (dashboard KPIs), student org managers need simplicity (intuitive submission flow) and transparency (approval status tracking), and passive viewers need relevance (priority-weighted content rotation) and reliability (no blank screens).
Challenges We Faced
Our team ran into several significant technical and design challenges throughout the project. Here's what we encountered and how we solved them:
The Approval Workflow Paradox
How do you give admins enough context to make good decisions while keeping reviews under 30 seconds? We designed a compact card layout showing campaign title, category, priority, date range, target screens, and preview image -- all visible without scrolling. Approve/reject actions are single-click with optional rejection reasons.
Offline Behavior for Display Clients
Library WiFi isn't always reliable. A blank screen is worse than a stale one. Our solution: service workers cache the last 10 campaigns locally. If the client loses connectivity, it continues rotating cached content and displays a small "Offline Mode" indicator. When reconnected, it syncs the latest content seamlessly.
Priority Weighting Algorithm
How do you balance fairness for small orgs against urgency for campus-wide alerts? We implemented a weighted rotation system where P(content_i) = w_i / sum(w_j) for all content j. The weight w_i depends on priority: Urgent (safety alerts) gets w=10, High (campus-wide events) gets w=5, Medium (club events) gets w=2, Low (general announcements) gets w=1. An urgent safety alert appears 10x more often than a low-priority flyer, ensuring critical information dominates screen time while still giving smaller orgs visibility.
Real-Time Screen Monitoring at Scale
How do you track dozens of screens without overwhelming the backend? Each display client sends a lightweight heartbeat ping (screen ID + timestamp) every 30 seconds via a dedicated /heartbeat endpoint. The dashboard polls a cached status endpoint every 10 seconds -- fast enough for near real-time without crushing the database.
State Management Across Multiple Clients
Getting the admin dashboard and multiple display clients to stay in sync was tricky. We initially tried WebSockets but ran into connection management issues when displays went offline and reconnected. We switched to Server-Sent Events for one-way updates from server to clients, which simplified the architecture significantly and proved more reliable for our use case.
Database Schema Design
We went through three iterations of our database schema before landing on the final design. The initial schema didn't properly handle campaign targeting (which screens should show which content), and we had to add a many-to-many relationship table. We also struggled with storing impression data efficiently -- logging every single display event created too many database writes. We ended up batching impression logs every 60 seconds per screen, which reduced database load by 98% while keeping the data accurate enough for analytics.
TypeScript Type Safety Across Layers
Keeping frontend and backend types in sync was a challenge until we discovered Zod schemas. By defining our data models once in Zod and sharing them across the monorepo, we caught type mismatches at compile time instead of runtime. This prevented bugs like the frontend expecting a createdAt string but the backend sending a Date object.
What We Learned
Technical Lessons:
SSE beats WebSockets for one-way updates. Server-Sent Events are simpler, more reliable for push notifications, and don't require connection management overhead. Building a design system upfront (buttons, cards, modals) with consistent spacing and colors made development way faster. Type safety across layers is non-negotiable -- shared Zod schemas caught a bunch of bugs during development that would've been runtime errors in production.
Product Lessons:
Infrastructure problems aren't always technical. UGA doesn't need more screens; it needs a system to make the ones it has useful. Sometimes the biggest impact comes from connecting things that already exist. Multi-persona platforms need intentional information architecture -- admins need dashboards with KPIs, student orgs need simple submission forms, passive viewers need readable content. Designing for all three required careful separation of concerns. Offline-first isn't optional for physical infrastructure. Display clients live in unpredictable network environments (libraries, student centers). Building for offline scenarios from day one prevented a total redesign later.
What's Next
Phase 1: Pilot Deployment (Spring 2026)
Deploy on 3-5 Main Library screens, onboard 5-10 initial student organizations (SGA, UGA Theatre, Career Center), and collect feedback on the approval workflow and screen visibility.
Phase 2: Analytics Buildout
Add impression heatmaps to see which screens get the most engagement, content performance metrics to track which campaigns drive the most awareness, and an A/B testing framework to test different messaging and visuals for the same event.
Phase 3: Campus-Wide Rollout
Expand to 20+ screens across Tate Center, MLC, Science Library, and Ramsey Center. Integrate with UGA's emergency alert system for safety notifications. Add QR code generation for campaigns so students can scan to RSVP or learn more.
Long-Term Vision:
ScreenNet becomes the central nervous system for campus communication -- replacing paper flyers, redundant Instagram posts, and fragmented email blasts with a single, authoritative, data-driven platform that serves students, administrators, and the broader UGA community.
Community Impact
ScreenNet directly benefits our campus across four dimensions. Connectivity -- student organizations reach thousands of students through screens in every building, not just the 50 people who follow their Instagram. Safety -- administrators can push urgent alerts (weather, security, health) to every screen instantly. Wellness -- mental health resources, counseling hours, and support services are promoted where students actually are: libraries, student centers, dining halls. Sustainability -- one digital campaign on 6 screens replaces 500 printed flyers that end up in the trash.
ScreenNet turns dead screens into a living, data-driven communication network that serves the entire campus community.
Built With
- bullmq
- cloudflare
- events
- framer-motion
- github-actions
- google-cloud
- google-cloud-run
- hono
- neon
- node.js
- postgresql
- radix-ui
- react
- recharts
- redis
- sentry
- tailwind-css
- typescript
- uga
- uga-cas
- vite
Log in or sign up for Devpost to join the conversation.