This is a submission for the GitHub Finish-Up-A-Thon Challenge
What I Built
The Course Allocation System is a department-level web portal that lets academic administrators manage lecturers, courses, and timetable allocations — and lets every lecturer log in to view their own assigned schedule.
But this isn't just a project. This is the project that started everything for me.
I began programming seriously in 2024. My first real full-stack challenge was to build something presentable for a school project deadline. I chose a course allocation system because it was a real problem my department had — lecturers not knowing their schedules, admins managing everything manually. I had three days. I built it. It worked just enough to demo and walk away from.
And then I abandoned it.
Not because I didn't care. Because I knew it was broken and I didn't yet know how to fix it properly. It sat in a GitHub repository with exactly three commits — "creataed a course allocation app", "updated the UI", "made changes to the UI" — and a codebase full of problems I could see but couldn't solve at the time.
The GitHub Finish-Up-A-Thon gave me the reason to come back and actually finish it.
Demo
🔗 New repository: https://github.com/sam-the-champ/CA-app
🔗 Old repository: https://github.com/sam-the-champ/course-allocation-app
What the revived app does:
- Admin logs in with securely hashed credentials stored in MongoDB
- Admin can add lecturers, create courses, and allocate courses to lecturers with day, time, level, and session details
- Dashboard shows live stats — total lecturers, total courses, allocated vs unallocated
- Lecturers log in and see only their own profile and timetable
- Logging out clears the session completely — the browser back button cannot return you into the dashboard
- Fully deployed: React frontend on Vercel, Express backend on vercel also.
🔗 Check it Live: https://course-allocation-app2.vercel.app/
The Comeback Story
Let me show you exactly what I came back to.
The Before: Three Commits and a Lot of Problems
Here is the entire commit history of the original project:
Three commits. Built in a rush. Pushed and abandoned.
This was the old admin dashboard:
And the old Add Lecturer page:
And the old lecturer dashboard — the page every lecturer was supposed to log into and see their courses:
The UI was functional enough to demonstrate. But under the hood, it was a completely different story.
Here is the single most embarrassing line in the old codebase:
That URL — https://literate-space-pancake-v9545...app.github.dev — is a GitHub Codespace URL. It was my live development environment URL, hardcoded directly into the frontend JavaScript. The moment I closed that Codespace, every single API call in the application broke. The app only ever worked on my machine, during that one session, on the day I built it.
This was not the only problem. Here is the full list of what I found when I came back:
Architecture:
- The entire frontend — HTML, CSS, and JavaScript files — lived inside the backend folder. One tangled directory for everything
- The
controllers/folder existed but was completely empty. Every piece of business logic was stuffed directly into the route files - The
Allocationmodel existed as a Mongoose schema but was never used anywhere. Allocations were embedded as arrays inside the Lecturer document
Security:
- Admin credentials were hardcoded as plain text directly in
authRoutes.js:username: 'admin', password: 'admin123' - Lecturer login did not issue a JWT token. It just returned the lecturer's raw ID string and called it a token
-
authMiddlewareexisted in the codebase but was applied to exactly zero routes — every endpoint was completely unprotected
Broken logic:
-
models/Admin.jsexportedmongoose.models.Admininstead of registering a model — meaning it exportedundefined. Admin authentication could never work with the database - The phone field was saved as
phonein routes but defined asphonenumberin the schema — phone numbers were silently dropped on every single save - The admin dashboard's course counter always returned
undefinedbecause of a nested array traversal bug - Logout was defined as
POSTon the server but called asGETfrom the frontend
This is what a first project built under deadline pressure looks like. It's not pretty. But it's honest.
The After: A Real Application
This is the new lecturer dashboard:
Same page. Same purpose. Completely rebuilt.
Here is everything that changed:
✅ Fully separated frontend (/frontend — React + Vite) and backend (/backend — Express) into independent deployable projects
✅ All business logic moved into proper controllers — authController, adminController, lecturerController — routes are now thin URL-to-function maps
✅ Fixed Admin.js model — it now correctly registers with mongoose.model('Admin', adminSchema) instead of exporting undefined
✅ Admin credentials stored in MongoDB, password hashed with bcrypt, created via a one-time npm run seed script — no credentials anywhere in source code
✅ Real JWT authentication for both admin and lecturer login, with protect, adminOnly, and lecturerOnly middleware applied to every protected route
✅ Allocation promoted to a proper first-class MongoDB collection with a compound unique index — no more embedded arrays
✅ All API calls centralised in a single src/api/index.js file using axios — base URL from environment variables — no hardcoded URLs anywhere in the application
✅ React frontend with React Router v6, AuthContext for shared authentication state, and <Navigate replace /> on logout so the back button cannot re-enter a protected route
✅ Unified field naming — phoneNumber consistent across model, controller, and frontend
✅ Global error handler middleware — consistent error response shape across every endpoint
✅ Backend deployed on Render, frontend deployed on Vercel
The before and after is not subtle. This went from something that only worked during one Codespace session to something I can actually hand to a department and say: use this.
My Experience with GitHub Copilot
Copilot was involved at every stage of this revival, and there were two moments where it genuinely changed what I was able to do.
Moment 1: The Codebase Audit
Before I wrote a single line of new code, I pasted the old route files into Copilot and asked it to identify weaknesses, inconsistencies, and broken logic. It found the hardcoded credentials, the unused middleware, the field name mismatch between phone and phonenumber, and the broken dashboard counter. Seeing the problems written out as a structured list — not buried in messy code — made the scope of the work clear and gave me a real roadmap. That audit became the plan.
Moment 2: The Vercel Seed Problem
This is the Copilot moment I will remember most. When I deployed the backend to Vercel, I realised I had no way to run npm run seed to create the admin account — because unlike Render, Vercel doesn't provide a persistent shell environment.
I described the exact problem to Copilot:
Copilot read my repository structure, confirmed it had found my seed.js file, explained exactly why the problem was happening, and then gave me two concrete solutions — convert the seed into a one-time API endpoint, or switch to a platform with shell access like Render.
It even gave me the exact code for the seed route and told me how to register it in server.js. Without this, admin login on the deployed version would have been impossible and I would have been stuck for hours trying to figure out why.
Day-to-Day Usage
Beyond those two moments, Copilot was my constant pair programmer throughout the rebuild:
When I was working on the LoginPage.jsx mobile view, I could describe what I needed in plain English and Copilot would generate the layout logic. When I was wiring up the React Router protected routes, it helped me get the <Navigate replace /> pattern right on the first try — which is what makes the logout-then-back-button behaviour work correctly.
The way I used Copilot was not "write this for me." It was more like having a senior developer sitting next to me who knew the codebase as well as I did and could answer "what's wrong here?" or "how do I do this properly?" in seconds instead of hours of searching.
What This Project Means
I started programming in 2024. This was my first full-stack project. It was messy, it was rushed, and I walked away from it feeling like I had failed at something I genuinely wanted to build.
Coming back to it — not just to touch it up but to understand every flaw and fix every single one — is the most I have learned in a single sprint since I started coding. I understand authentication flows, REST architecture, React state management, and deployment pipelines at a level I simply did not before.
And now there is actually a real application at the end of it. One that works. One I am proud of. One that my department could use.
That is what finishing things does.
Built with Node.js, Express, MongoDB, React, Vite, and GitHub Copilot.
Frontend: Vercel | Backend: Vercel










Top comments (3)
Lfg 🔥🔥
This is massive👍🏻
This is great 🔥