Skip to content

refactor(ai): migrate syllabus to structured topic model#47

Merged
imuniqueshiv merged 8 commits into
mainfrom
HyperAIWorkspace1
Jul 4, 2026
Merged

refactor(ai): migrate syllabus to structured topic model#47
imuniqueshiv merged 8 commits into
mainfrom
HyperAIWorkspace1

Conversation

@imuniqueshiv

@imuniqueshiv imuniqueshiv commented Jul 4, 2026

Copy link
Copy Markdown
Owner

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

  • Feature
  • Bug Fix
  • Documentation
  • Refactor
  • Performance Improvement
  • CI / Build
  • Other

What Changed?

  • Refactored syllabus JSON files to use structured topic objects (id, slug, title, displayOrder).
  • Replaced topic-name based routing with stable topicId identifiers.
  • Added getTopicById() helper for server-side topic resolution.
  • Updated syllabus and AI pages to resolve topic metadata from the server instead of trusting client-supplied values.
  • Updated AI workspace API to use topic lookup based on topicId.
  • Added shared syllabus and topic types.
  • Improved syllabus validation script for the new data structure.
  • Removed unused navbar code introduced during a previous UI update.

Screenshots (UI Changes Only)

N/A (No visual UI changes)


Testing

  • Verified syllabus navigation for all transformed subjects.
  • Verified AI workspace loads using topicId URLs.
  • Tested AI response generation for multiple syllabus topics.
  • Confirmed topic lookup and routing work correctly.
  • Ran formatting and static analysis checks successfully.

Checklist

  • My branch is up to date with the latest main.
  • My code follows the project's coding standards.
  • I have formatted the modified files (npx prettier --write <file>).
  • npm run format:check passes.
  • npm run lint passes.
  • npm run typecheck passes.
  • npm run build passes.
  • I have updated documentation if required.
  • I have tested my changes locally.
  • This Pull Request focuses on a single feature or fix.

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

  • New Features
    • Topic-based AI pages now open from a topic ID, with topic and module details shown automatically.
    • Topic links in the syllabus now use clearer titles and consistent, shareable URLs.
    • Syllabus content has been expanded with structured topic details across multiple subjects and semesters.
  • Bug Fixes
    • Improved reliability of AI/chat context by deriving topic information from the syllabus data instead of relying on manual input.

@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyper-learning-tech Ready Ready Preview, Comment Jul 4, 2026 10:15am

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This 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.

Changes

Topic model and AI workspace flow

Layer / File(s) Summary
Topic and syllabus type contracts
types/topic.ts, types/syllabus.ts
Adds Topic interface (id, slug, title, displayOrder) and SyllabusModule interface (id, number, title, hours, topics, questionIds, predictedQuestionIds).
Slug and topic ID generation utilities
lib/db/utils/slug.ts, lib/db/utils/topic-id.ts
Adds createSlug for canonical slugs and createTopicId that builds stable IDs from subject code, module number, and topic title.
Topic lookup by ID
lib/content/index.ts
Adds TopicLookupResult and getTopicById to find a topic and its module metadata within a syllabus.
AI workspace API topicId resolution
app/api/ai/workspace/route.ts
WorkspaceBody now uses topicId; the POST handler resolves topic/moduleTitle via getTopicById instead of taking them from the request.
AI page topic mode wiring
app/rgpv/[branch]/[semester]/[subject]/ai/page.tsx
Fetches topicData via getTopicById from a topicId query param, derives topicTitle/moduleTitle/isTopicMode, updates prompts, welcome message, header rendering, and WorkspaceChat wiring.
WorkspaceChat component topicId support
components/ai/workspace-chat.tsx
Props, initialPrompts shape, and POST payload switch from topic/module to topicId.
Syllabus UI topic object rendering
app/rgpv/[branch]/[semester]/[subject]/syllabus/page.tsx, components/syllabus/module-card.tsx
Module topics typed as Topic[]; topic links now use topic.id/topic.title and a topicId query parameter.
Syllabus content JSON migration
content/rgpv/common/semester-1/bt-201...bt-205/syllabus.json, content/rgpv/common/semester-2/bt-101...bt-202/syllabus.json
Module topics converted from string arrays to structured objects; module id formats and hours values updated across all subjects.
Syllabus migration validation script
scripts/migrate-syllabus.ts
New script scans, parses, validates syllabus JSON structure, prints per-file/aggregate reports, and exits with status codes based on validity.

Navbar Cleanup

Layer / File(s) Summary
Remove unused MagneticNavItem
components/navbar.tsx
Removes the internal MagneticNavItem helper component.

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
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: migrating the syllabus to a structured topic model.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch HyperAIWorkspace1

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Stale ?module= link is now a dead query param.

AIPageProps.searchParams in app/rgpv/[branch]/[semester]/[subject]/ai/page.tsx only declares topicId?: string now — the page no longer reads a module param. 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 (getTopicById requires a specific topicId), 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 win

Confusing nested main shadowing.

The outer main() (Line 209) defines an inner main(): 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

📥 Commits

Reviewing files that changed from the base of the PR and between 0e1b3a5 and 7a4ab4f.

📒 Files selected for processing (26)
  • app/api/ai/workspace/route.ts
  • app/rgpv/[branch]/[semester]/[subject]/ai/page.tsx
  • app/rgpv/[branch]/[semester]/[subject]/syllabus/page.tsx
  • components/ai/workspace-chat.tsx
  • components/navbar.tsx
  • components/syllabus/module-card.tsx
  • content/rgpv/common/semester-1/bt-201/syllabus.json
  • content/rgpv/common/semester-1/bt-203/syllabus.json
  • content/rgpv/common/semester-1/bt-204/syllabus.json
  • content/rgpv/common/semester-1/bt-205/syllabus.json
  • content/rgpv/common/semester-2/bt-101/syllabus.json
  • content/rgpv/common/semester-2/bt-103/syllabus.json
  • content/rgpv/common/semester-2/bt-104/syllabus.json
  • content/rgpv/common/semester-2/bt-105/syllabus.json
  • content/rgpv/common/semester-2/bt-202/syllabus.json
  • lib/content/index.ts
  • lib/db/repositories/pyq.repository.ts
  • lib/db/repositories/subject.repository.ts
  • lib/db/repositories/topic.repository.ts
  • lib/db/utils/slug.ts
  • lib/db/utils/topic-id.ts
  • lib/services/syllabus.service.ts
  • lib/services/topic.service.ts
  • scripts/migrate-syllabus.ts
  • types/syllabus.ts
  • types/topic.ts
💤 Files with no reviewable changes (1)
  • components/navbar.tsx

Comment thread app/api/ai/workspace/route.ts
Comment thread content/rgpv/common/semester-1/bt-205/syllabus.json
Comment thread lib/content/index.ts
Comment thread lib/db/utils/topic-id.ts
Comment thread scripts/migrate-syllabus.ts
Comment thread types/syllabus.ts
@imuniqueshiv imuniqueshiv merged commit 21b9df0 into main Jul 4, 2026
4 checks passed
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

🎉 Congratulations @imuniqueshiv!

Thank you for contributing to HyperLearningTech.

Your pull request has been successfully merged into main.

📦 Merge Summary

🚀 Keep Contributing

  • Follow the CONTRIBUTING.md guidelines.
  • Keep each Pull Request focused on a single feature or fix.
  • Run formatting, linting, type checking, and a production build before opening a PR.

Thank you for helping make HyperLearningTech better.

Happy Coding! 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant