Back to portfolioBringing Next.js-Style File-Based Routing to React + Vite

Bringing Next.js-Style File-Based Routing to React + Vite

Amir.Mahdi Sultani

Amir.Mahdi Sultani

·

April 15, 2026

node.jsreactfile-based routingnext.jsvitepackagenpmpluginjavascriptdev toolsfrontend developmentfront endpackage makingreact routerroutingopen sourceweb developmentdxfullstack journey

Why I Built Upcoming.js: Bringing Next.js-Style File-Based Routing to React + Vite

When I started building more serious React projects, one thing kept bothering me again and again: routing always felt more repetitive than it should be.

Every time I created a new page, I had to go back to the router, import the component, define the path manually, and keep repeating the same pattern as the project grew. It worked, but it did not feel elegant. It did not feel scalable. And more importantly, it did not feel natural.

At the same time, there was one thing I genuinely liked about Next.js: file-based routing.

That concept always felt clean to me. The folder structure itself becomes the route structure. Instead of manually registering everything, you simply create files and directories in a meaningful way, and the routing system understands your app. It removes noise and makes the project easier to think about.

But there was also a problem.

I liked that routing experience, yet I did not always want to use Next.js itself.

Sometimes I wanted the speed and simplicity of Vite.
Sometimes I wanted the flexibility of a standard React setup.
Sometimes I wanted to control the project architecture more directly without being tied to the full behavior and opinions of a larger framework.

That exact frustration became the reason I built Upcoming.js.


The Main Idea Behind Upcoming.js

Upcoming.js was born from a simple question:

Why can’t React + Vite developers enjoy a clean file-based routing experience without moving their whole project into a different framework?

That question stayed in my head for a long time.

I did not want to create something huge just for the sake of complexity. I wanted to create something focused, useful, and practical. I wanted a package that could make routing feel lighter, cleaner, and more enjoyable for developers who love React but also love the routing style of Next.js.

So the goal of Upcoming.js became very clear:

  • bring file-based routing
  • keep the React + Vite ecosystem
  • reduce manual route boilerplate
  • improve project organization
  • give developers a better experience without forcing them into a full framework

This was not just about code. It was about developer experience.


Why I Felt the Need to Build It

As projects grow, routing starts to affect architecture more than many people realize.

In small apps, writing routes manually is fine. But in larger apps, it starts becoming repetitive and noisy. A router file grows longer and longer. The app structure becomes harder to scan visually. Adding a single page may require touching multiple files. That is not always terrible, but it does create friction.

I wanted something that would make the project structure itself more expressive.

I wanted this:

  • if I create about/page.jsx, I get /about
  • if I create blog/[id]/page.jsx, I get /blog/:id
  • if I organize things into grouped folders, the app stays cleaner
  • if I add a page while development is running, the route should update naturally

That kind of workflow feels closer to how developers naturally think.

You do not think in terms of giant route configuration first.
You think in terms of pages, sections, features, and folders.

Upcoming.js was my answer to that way of thinking.


What Upcoming.js Actually Does

At its core, Upcoming.js is a package designed to bring Next.js-like file-based routing into React + Vite applications.

It allows developers to define application routes through the folder structure rather than declaring every route manually.

That means the file tree becomes meaningful not only for organization, but also for behavior.

A page folder can represent a route.
A bracket-based name can represent a dynamic parameter.
A grouped folder can help organize features without polluting the final URL.
A special not-found page can handle unmatched routes.
And lazy loading can improve route performance automatically.

So rather than being just “another router package,” Upcoming.js is really about changing the experience of building routes.


The Problem It Solves for Developers

The biggest value of Upcoming.js is not just that it reduces lines of code. It reduces friction.

Manual routing usually creates a few common problems:

1. Repetition

You keep importing pages and writing route definitions by hand.

2. Router files become messy

As the app grows, the routing configuration becomes another large file to maintain.

3. Slower feature growth

Adding a new page means more setup work than necessary.

4. Less intuitive structure

The folder tree and the route tree are separate concepts, even though they often describe the same thing.

5. Reduced clarity in large apps

When a project becomes bigger, it helps a lot if the route system is visible directly inside the file structure.

Upcoming.js tries to solve these pain points with a developer-friendly system that feels more natural for modern React apps.


My Goal While Building It

When I started working on this package, I had a few strong goals in mind.

I wanted it to feel simple

If a package solves a problem but creates confusion, then it is not a real improvement. I wanted Upcoming.js to feel straightforward.

I wanted it to feel familiar

Developers should not have to relearn all navigation logic. A routing package should improve workflow, not replace everything people already know.

I wanted it to be practical

This was not meant to be a toy project. It needed useful concepts like dynamic routes, route grouping, lazy loading, and not-found handling.

I wanted it to improve project organization

A routing system should not just resolve URLs. It should also help developers structure their app more cleanly.

I wanted it to be lightweight in spirit

The entire point was to get a better routing experience without dragging developers into an overly heavy setup.


The Core Concepts of Upcoming.js

Upcoming.js is built around several concepts that make it practical and enjoyable to use.

File-Based Routing

This is the heart of the package.

Instead of writing every route by hand, you create page files inside folders, and the route structure is derived automatically.

That means your route system becomes closely connected to how your project is organized.

This reduces boilerplate and makes the app easier to scan at a glance.

Dynamic Routes

Real applications need dynamic paths.

Blog posts, user profiles, product pages, dashboards, and more often require route parameters. Upcoming.js supports this through dynamic folder naming patterns.

This allows developers to define routes that depend on IDs, slugs, usernames, or any other parameter, while keeping the file-based system intuitive.

Route Groups

As apps grow, organization matters a lot.

Sometimes you want folders that exist for structure only, not for the final URL path. Route groups help solve that by letting developers organize parts of the app clearly without affecting the route output.

This is especially useful in larger projects where clean architecture matters as much as functionality.

Private Folders

Not every folder near a route should become part of the route tree.

Sometimes you want local components, helpers, or route-related utilities to live nearby. Private folders make that possible without accidentally exposing them as routes.

This improves code locality while keeping the route system clean.

Not Found Handling

A serious application needs a proper fallback page.

Upcoming.js supports a dedicated not-found page so unmatched routes can be handled in a clean, structured way. That is an important detail because it helps projects feel complete and production-aware.

Lazy Loading

Performance matters.

A routing system should not only feel clean to the developer, but also help the user by loading route code efficiently. Lazy loading helps separate page bundles so the app can load more intelligently.

That makes the experience better both technically and practically.

Live Route Updates

One of the most satisfying parts of developer experience is when the tools respond naturally to changes.

With Upcoming.js, the idea is that if you create a new page while working, the route system should recognize it and update without turning development into a manual refresh ritual.

This makes the workflow feel much smoother and more modern.


What I Used to Build It

Building Upcoming.js was not just about writing a few helper functions. It required combining several concepts and tools together in a thoughtful way.

React

Because the package is made for React applications, the component-based architecture of React sits at the center of the experience.

Vite

Vite was a very important choice because of its fast development workflow and plugin capabilities. Since the goal was to improve the React + Vite experience specifically, Vite became the perfect environment for this package.

Node.js

Since the package needed to work with the file system, scan folders, and generate route behavior, Node.js concepts became part of the implementation process.

React Router Concepts

Even though the goal was not to rebuild routing from scratch in a strange way, it was important that developers could still feel at home with familiar route behavior and navigation patterns.

npm Packaging

Publishing a package is very different from only building local application code. It requires cleaner structure, better assumptions, and more careful thinking about how other developers will use the tool.

That part of the process taught me a lot.


The Hardest Parts of Building Upcoming.js

This project was one of those experiences where the final product may look simple, but the path to get there is much harder than people expect.

That is actually one of the reasons I value it so much.

Turning an idea into a reusable package

Building something for yourself is one thing. Building something others can install, understand, and use is something else entirely.

A package has to be clearer. It has to be more stable. It has to think beyond one project.

That forced me to shift from “make it work for me” to “make it work for real use cases.”

Handling route generation properly

It sounds easy to say “read folders and create routes,” but actually designing that logic in a reliable and clean way is much more challenging than it seems.

You have to think about naming conventions, nested routes, parameters, ignored folders, fallback pages, and consistency.

Keeping the developer experience smooth

It was important to me that the package should not feel clunky.

If the system worked only after constant manual steps, it would miss the point. So making the experience feel smoother, especially during development, became a meaningful challenge.

Balancing simplicity and power

One of the hardest design challenges in any tool is deciding how much it should do.

Too little, and it feels useless.
Too much, and it becomes bloated.

I had to keep asking myself what really belongs in the package and what would only make it heavier without adding enough value.

Mental pressure and persistence

There is also the human side.

Building an npm package can be mentally exhausting, especially when you care about the result. There are moments where things break in unexpected ways, moments where a feature feels harder than it should, and moments where you question whether the idea is worth continuing.

That pressure is real.

But honestly, that is also part of what made this project meaningful for me. It forced me to push through uncertainty and keep building until the idea became something real.


What This Project Taught Me

Upcoming.js was not just a package. It was a learning experience that sharpened how I think as a developer.

It taught me to think like a tool builder

Application development and package development are different mindsets. This project helped me think more about reusability, developer ergonomics, and system behavior.

It taught me to care more deeply about DX

Developer experience is a real product concern. Good tools do not just function; they make developers feel faster, calmer, and more organized.

It taught me how much design matters in technical tools

Not visual design, but system design. Naming, behavior, predictability, and structure all matter.

It taught me patience

There were parts of the build that took more persistence than expected. That process reminded me that serious development often looks simple only after a lot of work has already been done.

It made me more confident

Finishing and publishing a package like this gave me a stronger sense that I can build not only apps, but tools that improve the way apps are built.


How to Think About Using Upcoming.js

The best way to think about Upcoming.js is this:

It is for developers who love the simplicity of file-based routing and want that experience inside a React + Vite workflow.

It is useful when:

  • you want cleaner route organization
  • you do not want long manual route files
  • you like the routing style of Next.js
  • you want to stay in React + Vite
  • you care about cleaner project structure
  • you want route creation to feel more automatic

It is especially nice for developers who think visually through folders and want the route system to reflect the architecture of the app more naturally.


A Conceptual Example of Usage

A simple mental model of usage looks like this:

Root page

If you create:

src/page.jsx

that becomes:

/

About page

If you create:

src/about/page.jsx

that becomes:

/about

Dynamic blog page

If you create:

src/blog/[id]/page.jsx

that becomes:

/blog/:id

Not found page

If you define a special not-found page in the expected place, it becomes your fallback route.

Organized internal folders

If you use grouped or private folders correctly, you can keep your route structure clean without cluttering the final paths.

This is what makes the package feel practical. It turns route creation into a much more natural extension of project structure.


Why This Package Matters to Me Personally

Upcoming.js is not just another project in a list.

It represents something bigger for me.

It represents the moment where I stopped only consuming tools and started building one.

It reflects the way I think about frontend development: not just as writing components, but as improving workflows, simplifying architecture, and making developer life better.

It also reflects a part of my personality as a developer. I do not just want to use systems. I like questioning them. I like asking whether something can be cleaner, faster, simpler, or more intuitive.

That mindset is what created Upcoming.js.


The Kind of Developer I Built This For

I built this package for developers who think something like this:

  • “I like React, but I want cleaner routing.”
  • “I enjoy Vite and do not want to leave it.”
  • “I love the routing style of Next.js, but I do not always want the full framework.”
  • “I want my folder structure to mean something.”
  • “I want less routing boilerplate.”
  • “I want a better developer experience.”

If you think like that, then Upcoming.js was built with someone like you in mind.


My Vision for It

What excited me most about building this package was not just solving a personal frustration. It was the idea that a focused tool can make developers feel more comfortable in their workflow.

I wanted Upcoming.js to feel like something that removes friction rather than adding magic for the sake of magic.

The best tools are often the ones that make you say:

“Of course this is how it should work.”

That feeling is what I was aiming for.


Final Thoughts

Upcoming.js started from a very real frustration and turned into one of the most meaningful technical projects I have built.

I created it because I wanted the elegance of file-based routing without having to move every project into a larger framework. I created it because I believed React + Vite developers deserved that experience too. And I created it because I wanted to build something that improves how people work, not just what they build.

This project challenged me technically, mentally, and creatively.

It made me think more deeply about architecture.
It made me think more seriously about packaging and reusability.
It made me appreciate the difficulty of making something feel simple.
And it made me more confident in my ability to build tools, not just applications.

At the end of the day, Upcoming.js is more than a routing package to me.

It is a statement about the kind of developer I want to become:

someone who builds useful things, solves real friction, and cares deeply about making development cleaner, smarter, and more enjoyable.

And that is exactly why I built it.

Comments

Sign in to join the conversation.

Sign in