refactor(ai): migrate syllabus to structured topic model#47
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR introduces a structured Topic model (id/slug/title/displayOrder) replacing plain topic strings across all RGPV syllabus JSON files, adds slug/topic-ID generation utilities and a topic lookup function, migrates the AI workspace route/page/chat component to use topicId instead of topic/module, updates syllabus UI typing/linking, adds a migration validation script, and removes an unused navbar component. ChangesTopic model and AI workspace flow
Navbar Cleanup
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant AIPage as AI Page
participant TopicLookup as getTopicById
participant WorkspaceChat
participant WorkspaceRoute as /api/ai/workspace
User->>AIPage: Navigate with topicId query param
AIPage->>TopicLookup: getTopicById(branch, semester, subjectCode, topicId)
TopicLookup-->>AIPage: TopicLookupResult (topic, module)
AIPage->>AIPage: Derive topicTitle, moduleTitle, isTopicMode
AIPage->>WorkspaceChat: Render with topicId prop
User->>WorkspaceChat: Send message
WorkspaceChat->>WorkspaceRoute: POST { topicId, message }
WorkspaceRoute->>TopicLookup: getTopicById(branch, semester, subjectCode, topicId)
TopicLookup-->>WorkspaceRoute: TopicLookupResult (topic, moduleTitle)
WorkspaceRoute-->>WorkspaceChat: AI response using resolved topic/moduleTitle
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/syllabus/module-card.tsx (1)
162-172: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winStale
?module=link is now a dead query param.
AIPageProps.searchParamsinapp/rgpv/[branch]/[semester]/[subject]/ai/page.tsxonly declarestopicId?: stringnow — the page no longer reads amoduleparam. This "Learn This Module" link therefore navigates to the generic (non-topic) AI page instead of a topic-scoped session, silently dropping the module context.Since there's no module-level lookup in the new model (
getTopicByIdrequires a specifictopicId), consider linking to the module's first topic, or removing this generic entry point if it's no longer supported by design.🐛 Suggested fix
<div className="mt-6 flex justify-end"> <Link - href={`/rgpv/${branch}/${semester}/${subject}/ai?module=${encodeURIComponent( - module.title - )}`} + href={ + module.topics?.[0] + ? `/rgpv/${branch}/${semester}/${subject}/ai?topicId=${encodeURIComponent( + module.topics[0].id + )}` + : `/rgpv/${branch}/${semester}/${subject}/ai` + } className="inline-flex items-center gap-2 text-sm font-medium text-blue-600" >🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@components/syllabus/module-card.tsx` around lines 162 - 172, The “Learn This Module” link is still passing a dead module query param, so it no longer reaches a topic-scoped AI session. Update the Link in ModuleCard to use the new topic-based flow by resolving the module’s first topic and passing its topicId to the ai route, or remove this entry point if module-level navigation is no longer supported. Make sure the navigation matches the AI page’s AIPageProps searchParams and the getTopicById-based lookup.
🧹 Nitpick comments (1)
scripts/migrate-syllabus.ts (1)
209-315: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConfusing nested
mainshadowing.The outer
main()(Line 209) defines an innermain(): MigrationSummary(Line 220) and calls it inside its own try/catch, while Line 317 invokes the outer one. It works, but the duplicated name and extra nesting hurt readability. Consider renaming the inner function (e.g.runValidation) or flattening so the summary logic and the exit-code handling live at top level.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/migrate-syllabus.ts` around lines 209 - 315, The migration script has confusing nested main() functions, with the outer main() wrapping an inner main(): MigrationSummary that does the actual validation work. Rename the inner function to something like runValidation or flatten the logic so there is only one main entry point, and keep the summary computation separate from the try/catch and process.exit handling for clearer control flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/api/ai/workspace/route.ts`:
- Around line 166-180: The topic lookup in route.ts is using hardcoded "common"
and "semester-1" in getTopicById, which breaks subjects outside that scope.
Update the AI flow so app/rgpv/[branch]/[semester]/[subject]/ai/page.tsx passes
the real branch and semester into WorkspaceChat, and extend WorkspaceChatProps
plus its request body to forward them to the API. Then change the getTopicById
call in the route handler to use the received branch/semester values instead of
literals so topic and moduleTitle resolve correctly for every subject.
In `@content/rgpv/common/semester-1/bt-205/syllabus.json`:
- Around line 20-50: The migration validator in scripts/migrate-syllabus.ts
still treats topics as strings, so it rejects object-shaped topic entries in
syllabus.json. Update the topic validation logic to read and validate topic.id,
topic.slug, topic.title, and topic.displayOrder instead of using typeof topic
!== "string" or topic.trim(), and change the duplicate check to dedupe by
topic.id so migrated syllabus files pass validation correctly.
In `@lib/content/index.ts`:
- Around line 68-74: The local SyllabusModule definition in the content index
duplicates the shared syllabus contract and is drifting from it. Replace the
inline interface in content/index.ts with the exported SyllabusModule from
types/syllabus.ts, and update any references in the surrounding content-loading
logic to use that shared type so fields like topics, questionIds, and
predictedQuestionIds stay consistent.
In `@lib/db/utils/topic-id.ts`:
- Around line 23-48: In createTopicId, the current validation only checks
moduleNumber < 1, so tighten it to reject non-integers and NaN before building
the ID. Also validate the result of createSlug(topicTitle) and throw when it
returns an empty string, since special-character-only titles would otherwise
produce a malformed topic ID. Keep the checks alongside the existing subjectCode
and topicTitle validation in createTopicId, and ensure the final return only
happens after all three inputs are confirmed valid.
In `@scripts/migrate-syllabus.ts`:
- Around line 15-23: The validation in migrate-syllabus still treats
Module.topics as string[] and validateSyllabus rejects the new topic object
shape, so update the Module type and all topic validation logic to accept { id,
slug, title, displayOrder } instead of trimming strings. Adjust the checks in
validateSyllabus to read topic.id/topic.slug/topic.title, remove the string-only
typeof/topic.trim assumptions, and dedupe topics by id or slug so migrated
syllabus files validate correctly.
In `@types/syllabus.ts`:
- Around line 3-11: The shared SyllabusModule contract is stricter than its
consumers and should match actual usage. Update SyllabusModule to make topics,
questionIds, and predictedQuestionIds optional so it aligns with
lib/content/index.ts and the syllabus page Module type, then have those
consumers import this shared type instead of redefining a local shape. Verify
any code using SyllabusModule handles missing arrays with defaults like ?? []
and still works with the canonical shared type.
---
Outside diff comments:
In `@components/syllabus/module-card.tsx`:
- Around line 162-172: The “Learn This Module” link is still passing a dead
module query param, so it no longer reaches a topic-scoped AI session. Update
the Link in ModuleCard to use the new topic-based flow by resolving the module’s
first topic and passing its topicId to the ai route, or remove this entry point
if module-level navigation is no longer supported. Make sure the navigation
matches the AI page’s AIPageProps searchParams and the getTopicById-based
lookup.
---
Nitpick comments:
In `@scripts/migrate-syllabus.ts`:
- Around line 209-315: The migration script has confusing nested main()
functions, with the outer main() wrapping an inner main(): MigrationSummary that
does the actual validation work. Rename the inner function to something like
runValidation or flatten the logic so there is only one main entry point, and
keep the summary computation separate from the try/catch and process.exit
handling for clearer control flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 789d53fe-401c-4795-970f-8dd5eaf46d99
📒 Files selected for processing (26)
app/api/ai/workspace/route.tsapp/rgpv/[branch]/[semester]/[subject]/ai/page.tsxapp/rgpv/[branch]/[semester]/[subject]/syllabus/page.tsxcomponents/ai/workspace-chat.tsxcomponents/navbar.tsxcomponents/syllabus/module-card.tsxcontent/rgpv/common/semester-1/bt-201/syllabus.jsoncontent/rgpv/common/semester-1/bt-203/syllabus.jsoncontent/rgpv/common/semester-1/bt-204/syllabus.jsoncontent/rgpv/common/semester-1/bt-205/syllabus.jsoncontent/rgpv/common/semester-2/bt-101/syllabus.jsoncontent/rgpv/common/semester-2/bt-103/syllabus.jsoncontent/rgpv/common/semester-2/bt-104/syllabus.jsoncontent/rgpv/common/semester-2/bt-105/syllabus.jsoncontent/rgpv/common/semester-2/bt-202/syllabus.jsonlib/content/index.tslib/db/repositories/pyq.repository.tslib/db/repositories/subject.repository.tslib/db/repositories/topic.repository.tslib/db/utils/slug.tslib/db/utils/topic-id.tslib/services/syllabus.service.tslib/services/topic.service.tsscripts/migrate-syllabus.tstypes/syllabus.tstypes/topic.ts
💤 Files with no reviewable changes (1)
- components/navbar.tsx
🎉 Congratulations @imuniqueshiv!Thank you for contributing to HyperLearningTech. Your pull request has been successfully merged into main. 📦 Merge Summary
🚀 Keep Contributing
Thank you for helping make HyperLearningTech better. Happy Coding! 🚀 |
Pull Request
Summary
Refactor the Hyper AI content pipeline by migrating syllabus data to a structured topic model with stable topic identifiers. This removes dependency on topic names, improves reliability, and prepares the project for future PostgreSQL integration.
Related Issue
Closes #
Type of Change
What Changed?
id,slug,title,displayOrder).topicIdidentifiers.getTopicById()helper for server-side topic resolution.topicId.Screenshots (UI Changes Only)
N/A (No visual UI changes)
Testing
topicIdURLs.Checklist
main.npx prettier --write <file>).npm run format:checkpasses.npm run lintpasses.npm run typecheckpasses.npm run buildpasses.Additional Notes
This refactor establishes a stable topic identity layer for Hyper AI. The API now resolves academic metadata server-side using
topicId, providing a foundation for the upcoming content repository abstraction and PostgreSQL migration without requiring future client-side routing changes.Summary by CodeRabbit