For several weeks, I hadn’t written any real Next.js or TypeScript code without relying heavily on AI tools.
During one of my Operating Systems classes, we were studying CPU scheduling algorithms. While going through the theory, a thought came to mind: why not build a visualizer for these algorithms?
It seemed like the perfect project. It would help me understand scheduling concepts more deeply, and it would also force me to start writing Next.js and TypeScript code manually again.
So I started the project.
That’s when reality hit.
The Reality Check
I quickly realized I couldn’t write much beyond the basic Next.js boilerplate.
When I tried to create a simple dummy data object, I hesitated on the syntax. When I needed to sort an array of processes by arrival time, my mind went blank. Because most of my recent coursework had focused on C++ and Java, I even caught myself typing int instead of number in TypeScript.
This was an uncomfortable but important realization:
skills fade when you stop practicing them.
Over time, I had started letting AI handle a lot of the small details like syntax, structure, boilerplate. Tools like ChatGPT and Claude were helpful, but I had slowly offloaded too much of the basic thinking to them.
Eventually, I noticed something worrying: I had begun to lose the ability to write those things independently.
This project became my reset.
I decided on a simple rule: no AI for core logic.
If I forgot how something worked, I would check documentation, Stack Overflow, or official references the traditional way.
At first it felt slow and frustrating. But gradually things came back; TypeScript types, array methods, language quirks. It was like loosening a rusted bolt: difficult at first, but easier once it started moving.
One thing that came back quickly was my comfort with designing TypeScript interfaces. That kind of structural thinking tends to stick longer than syntax details.
Finding the Right Balance with AI
At first, I thought the solution was simple: no AI at all.
But that isn’t realistic either.
Modern software development involves tools, and AI is increasingly one of them. Completely rejecting it would be just as extreme as depending on it for everything.
Instead, I changed how I used AI.
Rather than asking it to generate the application, I used it to:
- Discuss component structure and interface design.
- Review code I had already written.
- Question naming choices and architecture decisions.
- Suggest clearer variable, type, and function names.
- Explore design tradeoffs before committing to an approach.
In other words:
I wrote the code. AI reviewed the work.
That distinction mattered.
The result was cleaner code, better naming, and a more organized folder structure without losing the actual learning process.
What I Built
The result is an interactive Process Scheduling Simulator.
Users can:
- Enter a list of processes with arrival times, burst times, and optional priorities.
- Run multiple scheduling algorithms.
- View results instantly through Gantt charts and detailed metrics tables.
The simulator currently supports six classic CPU scheduling algorithms:
- FCFS - First Come First Serve
- SJF - Shortest Job First (non-preemptive)
- SRTF - Shortest Remaining Time First (preemptive)
- Priority Scheduling - both preemptive and non-preemptive
- Round Robin - with configurable time quantum
For each algorithm, the system calculates:
- Completion Time
- Turnaround Time
- Waiting Time
- Response Time
It also calculates averages across processes.
One small but important detail the simulator handles correctly is CPU idle time, which is easy to overlook when first learning scheduling algorithms.
Tech Stack and Architecture
- Framework: Next.js (App Router)
- Language: TypeScript 5
- UI Components: shadcn/ui + Radix UI
- Styling: Tailwind CSS v4
- Forms & Validation: React Hook Form + Zod
- Icons & Theming: Lucide React, next-themes
The architecture intentionally separates algorithm logic from the UI layer.
This made the scheduling logic easier to test and reason about independently from the interface.
Using Zod with React Hook Form made validation surprisingly clean, especially with dynamic numbers of processes and constraints between fields.
TypeScript’s strict typing also helped ensure that scheduling logic stayed consistent across different algorithms.
The Decision Not to Over Abstract
At one point, I considered creating shared abstractions for the scheduling algorithms to reduce duplication.
In the end, I decided not to do that.
The entire purpose of this project was to understand the algorithms themselves.
FCFS is extremely simple.
SRTF requires tracking remaining burst time at each time step.
Round Robin requires maintaining a ready queue and time quantum.
These algorithms work differently enough that forcing them into a common abstraction would actually hide the differences I wanted to understand.
Sometimes explicit code is better than clever abstractions, especially when the code itself is part of the learning process.
Type Safety
To avoid fragile string comparisons, algorithm identifiers are stored as constants (fcfs, sjf, srtf, etc.).
This eliminates magic strings and gives strong TypeScript autocomplete and type safety across the scheduling logic.
Small decisions like this make the codebase easier to maintain as new algorithms are added.
What I Actually Learned
The obvious takeaway is that I now understand scheduling algorithms much more clearly; especially concepts like:
- Preemption
- Context switching
- Starvation in SJF
- The impact of time quantum in Round Robin
But the more interesting lesson was about my relationship with AI tools.
There are two extreme approaches:
Ask an AI to generate the entire project in minutes.
You get working code, but you learn very little.Refuse to use AI at all out of principle.
This is noble, but not realistic in modern development.
The approach that worked best for me was the middle ground:
Write the logic yourself. Let AI help refine it.
This kept the thinking process mine, while still benefiting from an additional pair of eyes.
Try It
The project is open source on GitHub:
🔗 https://github.com/jithesh-poojari/process-scheduling-visualization
Live demo:
🔗 https://process-scheduling-simulator-nine.vercel.app/
If you're studying Operating Systems and want to see how scheduling algorithms behave in practice, this tool may help.
Upcoming ideas include:
- Multilevel Queue Scheduling
- Multilevel Feedback Queue Scheduling
- Timeline animations
- Automated tests
- CSV import of inputs and export of results
- Step-by-step execution with explanations
The best learning projects are the ones that feel slightly too difficult at the start. If everything feels comfortable from line one, you're probably not growing.
Top comments (6)
Hey Jithesh Poojari, I recently built something similar—a CPU scheduler visualizer in React—and your TypeScript/Next.js approach with those Gantt charts caught my eye. Separating the algo logic from the UI like you did makes sense for testing, and using AI just for reviews is a balanced take I've been experimenting with too. Curious how the priority scheduling preemption turned out in practice—checked out your repo.
@vasughanta09 Thank you for reading. The preemptive algorithm implementation gave me a bit of a headache at first. Initially I approached it like the non-preemptive versions and simply iterated through each time unit, but I wasn't tracking the remaining burst time, so the results looked similar but weren't correct. After reviewing it, I added remaining time tracking, completion status for each process, and a completed process counter. The loop then runs until all processes finish, checking arrival time and selecting the appropriate process based on the algorithm (shortest burst or priority). I tried to keep the code as readable as possible.
The part about typing
intinstead ofnumberafter years of Python really resonated — that muscle memory conflict is the hardest part of switching languages. Did you find TypeScript's strict mode helped catch those habits faster?Yes @klement_gunndu , strict mode definitely helped. TypeScript forces you to be explicit about types, so mistakes like using the wrong type or missing properties get caught early. I had used it before, so the familiarity came back pretty quickly.
This really resonates. I landed on almost the exact same approach you describe — "I write the code, AI reviews the work" — but from the opposite direction. I was leaning too heavily on AI for generating content at scale (programmatic SEO across 12 languages), and the quality suffered because I wasn't deeply understanding the data transformations happening under the hood.
Your point about not over-abstracting the scheduling algorithms is spot on. I made a similar mistake early on with data processing pipelines — tried to create a universal "page generator" that handled stocks, sectors, and ETFs identically. The abstractions hid important differences in how each data type needed to be processed. Explicit code that shows the differences is more maintainable than clever abstractions that hide them.
The tech stack choice is solid too. Zod + React Hook Form is an underrated combo for complex validation. I've been using a similar pattern for financial data validation where constraints between fields matter (like your process arrival/burst time relationships).
Nice project — the live demo is clean.
@apex_stack Thank you for the thoughtful comment; I really appreciate it.
I completely relate to what you mentioned about leaning too heavily on AI. It definitely saves time, but if you’re not careful you stop understanding what’s actually happening under the hood. That’s why I tried to follow the approach of writing the core logic myself and using AI mainly for review and discussion.
The abstraction point was also a deliberate decision. Since the goal of this project was to understand the algorithms, I avoided heavy abstraction. In this case, explicit code makes the differences between algorithms clearer and easier to reason about.
One thing I’m still working on is avoiding over-planning and premature optimization. I tend to spend too much time designing things before writing the code, so learning where to stop abstracting is something I’m actively improving.
And yes, Zod + React Hook Form has been great so far. Combined with shadcn/ui it makes handling complex forms much easier.
Thanks again for taking the time to check out the project and the demo.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.