diff --git a/CHANGELOG.md b/CHANGELOG.md index 9538be6..16ab1f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,14 @@ Format: [Keep a Changelog](https://keepachangelog.com/); versioning: [SemVer](ht ## [Unreleased] +### Fixed +- Phone header: Studio, data saver and the theme switch were off-screen below ~560 px. Header, Studio and /try now fit 360 px (Phase 23) + ### Added - Weak spots on Saved: wrong quiz answers become a personal revision reel of the explanations you missed (Phase 22) - Study notes `/notes/[id]` and `GET /api/lectures/[id]/notes`: a timestamp-linked study sheet per session, as Markdown or PDF (Phase 22) - Data saver: a header switch (automatic on Save-Data and 2G/3G) that serves lighter Cloudinary renditions and the `sd` streaming ladder; 33–76% fewer bytes measured (Phase 21) +- `/judges`: the submission requirements mapped to 14 Cloudinary capabilities, live URLs and a 90-second test; revision reel on `/saved` (Phase 20) - Concept Map `/concepts` and Compare view `/concepts/[key]`: the same concept from every teacher as one Compare Reel (Phase 19) - Cloudinary asset index: tags and contextual metadata on each session's asset, synced from the Studio and read back with the Search API (Phase 19) diff --git a/README.md b/README.md index 33eb937..d0070b4 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ Colleges, clubs and coaching institutes record hundreds of hours of lectures and | **Data saver** | One switch (and automatic on Save-Data or 2G/3G) serves smaller, lower-quality Cloudinary renditions: thumbnails 76% lighter, clips and reels 38–41%, and a streaming ladder that tops out at 0.9 Mbps instead of 3.4. Built for India’s mobile data. | | **Weak spots** | Quiz mistakes are remembered on your device and come back as **one Cloudinary reel of exactly the explanations you missed**, with the answer and the second to jump to. Get a question right and it leaves the list. | | **Study notes** | Every session has a study sheet at `/notes/[id]`: summary, key concepts, chapters and the quiz with answers, each point linked to its timestamp. Copy it as Markdown, download it, or save it as a PDF. | +| **Revision reel** | On `/saved`, the latest saved moments from any sessions play as one labelled video: a revision reel for the night before an exam. | | **Study Packs** | Every session gets a summary, key concepts, a quiz whose explanations **play the moment** the teacher explains it, and a "Session in 60 seconds" highlight reel. Pravaha generates them automatically from the transcript. | | **Moments** | One tap turns any cited clip into a vertical, AI-cropped, subtitled short for WhatsApp or Instagram, with its own share page and preview card. The short is just a Cloudinary URL; nothing is rendered. | | **Insights** | Organizers see what learners ask, the **knowledge gaps** the library can't answer yet (what to record next), and which Moments get shared. Every report downloads as CSV. Visitors can explore a read-only demo of the Studio. | @@ -164,6 +165,8 @@ Diagrams and reasoning: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) · [`docs ## How to test it +> **Judges:** [`/judges`](https://pravaha-cyan.vercel.app/judges) maps the submission requirements to the Cloudinary features, with live URLs and a 90-second test. + Open the live app at **[pravaha-cyan.vercel.app](https://pravaha-cyan.vercel.app)**. Learners need no login. 1. On the home page, type a question or tap a suggestion. Try "Why should the learning rate decrease during training, and how do adaptive optimizers handle it?": live progress appears, then one answer citing two professors from two institutes, plus an Answer Reel. Or ask in Hindi: "ओवरफिटिंग क्या है?" diff --git a/docs/DEMO.md b/docs/DEMO.md index 4be5b80..ccf6f79 100644 --- a/docs/DEMO.md +++ b/docs/DEMO.md @@ -29,6 +29,15 @@ Never show setup, code, dashboards or waiting. Every shot is the problem, the pr **Study shots (if there is time):** answer a quiz question wrong → `/saved` → **Play my weak-spot reel** ("What you get wrong comes back as video.") → a session’s **Study notes** → **Download .md** ("Every point links to the second the teacher said it.") **Bonus shot (if there is time):** header → **Data saver** on → the same answer reel and thumbnails reload visibly lighter. Voice-over: "Built for India’s mobile data: one switch, and Cloudinary serves everything at a fraction of the bytes." +## Phase 18–20 scenes (Oct 3) — swap in for the 2:06–2:35 shots if time is tight + +| Shot | Voice-over | +|---|---| +| Ask "What is the bias-variance trade-off?" → the answer says honestly the lecturer never uses that phrase, then explains the related ideas with clips | "It doesn’t bluff. If the lecturer never said it, Pravaha says so and teaches the closest ideas." | +| Ask the same in Hindi: "ओवरफिटिंग क्या है?" → Hindi answer citing English lectures | "Ask in Hindi, answer from English lectures." | +| `/concepts/overfitting` → play the Compare Reel: three professors, labelled | "Same idea, three teachers, one video, until one explanation clicks." | +| `/learn` → "Choosing a learning rate" → 4-step course video | "Any topic becomes a short course, ordered basics first, edited by Cloudinary." | +| `/judges` → capability list → Studio → Cloudinary asset index (Search API) | "Every capability is listed with live URLs. Even our tags are read back from Cloudinary’s Search API." | ## Pre-Recording Checklist diff --git a/docs/IMPLEMENTATION_PLAN.md b/docs/IMPLEMENTATION_PLAN.md index 7fcd947..a6b5a5a 100644 --- a/docs/IMPLEMENTATION_PLAN.md +++ b/docs/IMPLEMENTATION_PLAN.md @@ -96,3 +96,5 @@ The core loop (Phases 01–09) is built and verified on real Cloudinary + Neon. | 19 | Concept Map & Cloudinary asset index | Same concept, every teacher, as one Compare Reel; tags + contextual metadata on Cloudinary assets, read back with the Search API | ✅ done (Oct 3) | | 21 | Data saver | Light Cloudinary renditions (35–76% fewer bytes, sd streaming ladder) for slow or metered connections; follows Save-Data and 2G/3G automatically | ✅ done (Oct 3) | | 22 | Weak spots & study notes | Quiz mistakes become a personal revision reel; every session exports a timestamp-linked study sheet (Markdown / print) | ✅ done (Oct 3) | +| 20 | Judges page & revision reel | `/judges` maps the brief to Cloudinary capabilities with live URLs; saved moments replay as one reel | ✅ done (Oct 3) | +| 23 | Phone layout | Header, Studio and /try fit a 360 px phone; e2e guard | ✅ done (Oct 3) | diff --git a/docs/SUBMISSION_CHECKLIST.md b/docs/SUBMISSION_CHECKLIST.md index 677c249..1581d54 100644 --- a/docs/SUBMISSION_CHECKLIST.md +++ b/docs/SUBMISSION_CHECKLIST.md @@ -15,9 +15,11 @@ Deadline: submit by **Oct 3, 2026**; code freeze **Oct 4, 00:15 IST**. Submit vi - [x] Learner flows (Watch, Find, Ask, Moments) work without login (Oct 2: Playwright smoke tests 12/12 against production, desktop and mobile) - [x] Demo library: 6 public sessions (NPTEL excerpts, CC BY-NC-SA, credited in the README), uploaded through the production pipeline on Oct 2 - [x] Organizer and enterprise features merged and checked on Vercel previews (Oct 2–3): demo Studio, Insights charts and CSV export, LMS embed, Privacy and Terms, health endpoint -- [ ] **Cloudinary credits:** 24.3 of 25 used on Oct 3 (free plan). Upgrade, or confirm the reset date is before judging, so new answer clips and Moments keep generating +- [ ] **Cloudinary credits:** the Admin API reported 14.1 of 25 used (56%) at its last update (Oct 2). Every new reel, Moment and Compare Reel spends some, so avoid regenerating them in bulk before judging, and re-check `api.usage()` on submission day - [ ] Trials decision after that: keep `/try` paused (`TRIALS_PER_DAY=0`) or re-enable (`TRIALS_PER_DAY=5`, then redeploy) +- [x] Phone check at 360 px on every key page (Oct 3, Phase 23): header controls reachable, no sideways scroll + ## Repository - [x] Public repo: `Monolithic-Dev/Pravaha` (own repo is allowed by HackIndia's FAQ) - [ ] README explains track, problem, Cloudinary usage, how to test — with live URL, screenshots, demo link (all done except the demo link; screenshots retaken with the real library on Oct 2) @@ -25,6 +27,9 @@ Deadline: submit by **Oct 3, 2026**; code freeze **Oct 4, 00:15 IST**. Submit vi - [ ] Setup instructions a stranger can follow cold (`SETUP.md`) - [x] No API keys or credentials anywhere in history — `git log -p | grep -iE "api_secret|sk-ant|postgres://|passcode"` returns only env-variable references (checked Oct 2) +- [ ] Studio → **Cloudinary asset index** → Sync tags run once on production, so the Search API shows tagged assets +- [x] `/judges` page maps the brief to Cloudinary capabilities and the 90-second test (Phase 20) + ## Demo - [ ] 2–4 minute video recorded per `DEMO.md` (target 2:45), publicly viewable link (check credits first: see its pre-recording checklist) - [ ] Demo video link added to the README diff --git a/docs/TESTING.md b/docs/TESTING.md index 9b1e062..1130c97 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -22,6 +22,12 @@ Scope: the things that would embarrass the product in front of a judge or corrup Against the **deployed** `APP_URL`: home → search a known phrase → result opens `/watch/id?t=` at the right second → Ask a known question → ≥1 citation card → open Moment sheet. Run before recording the demo and before submitting. +### More end-to-end specs (all run against the deployed `APP_URL`, `--project=desktop --project=mobile`) +- `judges.spec.ts`: the judges page, the concept map with its compare reel, `/learn` +- `data-saver.spec.ts`: the header switch makes Cloudinary thumbnails `w_320,q_auto:low`, is remembered, and a session streams the `sp_sd` ladder +- `revision.spec.ts`: a wrong quiz answer appears under Weak spots with a revision reel and clears; study notes carry timestamp links and download as Markdown +- `mobile.spec.ts`: at 360 px the header's Studio, data saver and theme controls are on screen and no page scrolls sideways + ## AI Eval (`pnpm eval:ask`) 10 questions (7 answerable, 3 not) against the demo library; results recorded in `AI_EVALUATION.md`. diff --git a/docs/UX_UI.md b/docs/UX_UI.md index 5572e12..425d990 100644 --- a/docs/UX_UI.md +++ b/docs/UX_UI.md @@ -70,7 +70,7 @@ Skeletons, never bare spinners. 404 session → "This session isn't available." ### Motion & shell (v3) - `rise` (staggered entrance), `word-in` (answer reveal), `lift` (hover), `spinner`; all disabled under `prefers-reduced-motion` -- Sticky blurred header with the Pravaha mark (also the favicon, `app/icon.svg`), Library and Studio links, a skip link, and a footer +- Sticky blurred header with the Pravaha mark (also the favicon, `app/icon.svg`), the page links (Library, Learn, Concepts, Saved, Studio) and the data saver and theme switches. On a phone the links drop to a second, sideways-scrolling row so nothing is pushed off-screen (Phase 23); a skip link, and a footer - Home: "How it works" in three steps under the Ask bar - `/` or Ctrl/⌘K focuses the Ask bar from anywhere diff --git a/docs/phases/PHASE-20-judges-page-revision-reel.md b/docs/phases/PHASE-20-judges-page-revision-reel.md new file mode 100644 index 0000000..145724a --- /dev/null +++ b/docs/phases/PHASE-20-judges-page-revision-reel.md @@ -0,0 +1,15 @@ +# Phase 20 — Judges page and revision reel + +**Status: DONE (Oct 3)** · branch `feature/judges-page-revision-reel` + +## Why +A hackathon is judged in minutes. The product was strong but a judge had to discover how Cloudinary is used by reading code and docs. This phase puts the evidence in the product. + +## What shipped +1. **`/judges`** (`src/app/judges/page.tsx`, `src/lib/capabilities.ts`): the submission requirements mapped to where each is met, a 90-second test with deep links, 14 Cloudinary capabilities (what each does, where to see it, which file), and the live Cloudinary URLs generated from the real library. `tests/unit/capabilities.test.ts` fails if any listed file doesn't exist, so the page can't drift from the code. +2. **Revision reel** on `/saved`: the latest saved moments, from any sessions, as one labelled `fl_splice` video. Saved moments stay on the device; only the Cloudinary URL is built from them. +3. Playwright smoke tests for `/judges`, `/concepts` and `/learn`; the demo script and submission checklist updated. + +## Findings from the Oct 3 architecture review +- Cloudinary credits were 14.1 of 25 (56%) at the Admin API's last update (Oct 2): enough for judging if reels aren't regenerated in bulk. The biggest consumers are `sd_video_second` and AI hover previews. +- The Gemini free quota remains the main production risk; Groq is the working fallback. diff --git a/docs/phases/PHASE-23-mobile-layout.md b/docs/phases/PHASE-23-mobile-layout.md new file mode 100644 index 0000000..840acf4 --- /dev/null +++ b/docs/phases/PHASE-23-mobile-layout.md @@ -0,0 +1,17 @@ +# Phase 23 — Phone layout + +**Status: DONE (Oct 3)** · branch `fix/mobile-layout-audit` + +## Why +A 360 px audit of every key page (Playwright, `isMobile`, scanning for elements past the viewport) found one real bug that appeared on **every page**: the header's single row needed ~560 px, so on a phone **Studio, the data saver switch and the theme switch were off-screen and unreachable** (the page clips horizontal overflow, so there was no scrollbar to hint at them). Judges often open a link on a phone. + +## What changed +- **Header:** on phones the logo and the two switches share row one; the page links sit on a second row that scrolls sideways if it must. From `sm` up it is the same single row as before (checked at 1280 px). +- **Studio:** the page grid had no explicit column, so its content's minimum width pushed it 19 px past the screen. `grid-cols-1` fixes it. +- **/try:** the three-step progress bar wraps instead of overflowing. +- `tests/e2e/mobile.spec.ts` asserts, for 8 pages at 360 px, that Studio, data saver and the theme switch are on screen and the page doesn't scroll sideways. + +## Verified +Before: 11 of 11 audited pages had off-screen header controls. After: 0 offenders on all 11 pages (home's remaining hits are decorative clipped backgrounds). + +Bundled in this PR: the judges page and revision reel (Phase 20), which touch the same header and footer. diff --git a/src/app/globals.css b/src/app/globals.css index 444cfe4..75d9ff8 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -180,3 +180,11 @@ body { .playhead { width: 100%; } .lift, .lift:hover { transition: none; transform: none; } } + +/* A row that scrolls sideways without showing a scrollbar (the phone header's page links). */ +.no-scrollbar { + scrollbar-width: none; +} +.no-scrollbar::-webkit-scrollbar { + display: none; +} diff --git a/src/app/judges/page.tsx b/src/app/judges/page.tsx new file mode 100644 index 0000000..e5e0132 --- /dev/null +++ b/src/app/judges/page.tsx @@ -0,0 +1,109 @@ +import type { Metadata } from "next"; +import Link from "next/link"; + +import { UnderTheHood } from "@/components/UnderTheHood"; +import { CAPABILITIES } from "@/lib/capabilities"; +import { getConcept, listConcepts } from "@/lib/concepts"; +import { conceptHoodItems, sessionHoodItems, type HoodItem } from "@/lib/hood-items"; +import { getLecture, getSegments, listLectures } from "@/lib/lectures"; +import { getStudyPack } from "@/lib/study-packs"; + +export const dynamic = "force-dynamic"; + +export const metadata: Metadata = { + title: "For judges — Pravaha", + description: "How Pravaha uses Cloudinary, mapped to the hackathon's requirements, with live URLs and a 90-second test.", +}; + +const REQUIREMENTS: [string, string][] = [ + ["Cloudinary is an active part of the product", "Media in is raw video; transcripts, chapters, streams, clips, reels, cards and tags all come from Cloudinary. Without it there is no product."], + ["Upload, manage, transform, optimize, search, deliver", "Signed upload · tags and context · Search API · splice, crop, caption, preview transformations · f_auto/q_auto · HLS delivery."], + ["A live working demo", "This site. Six real NPTEL sessions, no login for learners."], + ["Public repo with setup instructions", "github.com/Monolithic-Dev/Pravaha, SETUP.md."], + ["README: track, problem, Cloudinary usage, how to test", "Track 3 (Your Media-Savvy Startup); see the README."], +]; + +const STEPS: [string, string, string][] = [ + ["Ask", "Type: “What is the bias-variance trade-off?” The answer cites clips; open one. Try it in Hindi: “ओवरफिटिंग क्या है?”", "/"], + ["Watch the answer", "Tap “Watch the answer”: moments from different lecturers as one Cloudinary-edited video.", "/"], + ["Compare teachers", "Open the Overfitting concept: three lecturers, one video.", "/concepts/overfitting"], + ["Build a course", "Ask for “Choosing a learning rate”: a 4-step course, one video.", "/learn?topic=Choosing%20a%20learning%20rate"], + ["Share a Moment", "On any clip tap “Share as Moment”: vertical, speaker-tracked, captioned.", "/search?q=overfitting"], + ["See the proof", "Open “Cloudinary under the hood” at the bottom of a session, answer or concept.", "/#library"], +]; + +export default async function JudgesPage() { + const [lectures, concepts] = await Promise.all([listLectures({ includeAll: false }), listConcepts()]); + const lecture = lectures[0] ? await getLecture(lectures[0].id) : null; + const shared = concepts.find((c) => c.entries.length > 1); + const [segments, pack, concept] = await Promise.all([ + lecture ? getSegments(lecture.id) : [], + lecture ? getStudyPack(lecture.id) : null, + shared ? getConcept(shared.key) : null, + ]); + const items: HoodItem[] = [ + ...(lecture && segments.length ? sessionHoodItems(lecture, segments, pack?.highlights) : []), + ...(concept ? conceptHoodItems(concept.key, concept.moments) : []), + ]; + + return ( +
Track 3 · Your Media-Savvy Startup
++ Pravaha turns lecture recordings into knowledge you can ask. Every answer is a clip of the teacher saying it, and the clip, + the reel, the share card and the Hindi subtitles are all Cloudinary. This page maps that to the submission requirements. +
+ +{c.name}
+{c.does}
+
+ See it: {c.see} · {c.code}
+
Generated from the real library right now. Open any of them.
+