Online tech learning platform in Kinyarwanda
# Ubuhanga — Tech Tutorials mu Kinyarwanda
Ubuhanga ni urubuga rw'uburezi rwa kubuntu rutanga amasomo y'ubumenyingiro mu ikoranabuhanga mu rurimi rw'Ikinyarwanda.
A free, open learning platform delivering tech tutorials in **Kinyarwanda**. A product of Techinika.
## Stack
- **Framework:** Astro v6 (SSR — `output: "server"`)
- **Adapter:** `@astrojs/vercel`
- **PWA:** `@vite-pwa/astro` — manifest + Workbox service worker, install button on mobile bottom nav / desktop footer (peer dependency on Astro <6 resolved via `overrides` in `package.json`)
- **Auth:** Firebase Auth (Google sign-in for admin panel + comments), session cookies via Firebase Admin SDK
- **Database:** Firebase Firestore (videos, playlists, categories, comments, subscribers, auditLog)
- **Ads:** Google AdSense (`ca-pub-1268572467254702`)
- **Styling:** CSS custom properties with light/dark theme toggle (persisted to localStorage)
- **Fonts:** Lexend (display) + Inter (body) via @fontsource (self-hosted)
- **Linting & Formatting:** ESLint (flat config) + Prettier with `prettier-plugin-astro`
- **Security:** CSP with nonces, rate limiting, security headers via middleware
## Routes
| Path | Description |
|---|---|
| `/` | Homepage — hero, featured videos, playlists, newsletter |
| `/videos` | All videos with client-side category filter |
| `/videos/[slug]` | Single video — YouTube embed, comments, related sidebar, view counter |
| `/playlists` | All curated playlists |
| `/playlists/[slug]` | Single playlist — ordered video list with duration |
| `/search` | Client-side search across all video fields |
| `/ask` | Request a tutorial or ask a tech question — submitted to Firestore |
| `/about` | About Ubuhanga and Techinika |
| `/terms` | Terms of Service |
| `/privacy` | Privacy Policy |
| `/admin` | Admin sign-in with Google |
| `/admin/videos` | Manage videos (list, create, edit, delete) — paginated |
| `/admin/playlists` | Manage playlists (list, create, edit, delete) — paginated |
| `/admin/cat …