/lovable-issues

Fixing 404 Errors on Page Refresh in Lovable SPAs

Explore why SPA routing fails on refresh in Lovable apps, discover essential fixes, and learn best practices for seamless SPA configuration.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free No-Code consultation

Why SPA Routing Fails on Refresh in Lovable Applications

 
The Role of Routing in SPA
 

  • Single Page Applications (SPAs) load a single HTML file and use JavaScript to change what is displayed on the page. This means that navigation happens inside your browser without making a full request to the web server.
  • When you click a link or interact with the app, the JavaScript code intercepts the event and changes the view. The browser’s address bar is updated even though the page itself is not reloaded from the server.

 
What Happens on a Page Refresh
 

  • When you refresh, the browser sends a request for the exact URL to the server. In SPAs, many routes are handled on the client side. The server is not aware of these virtual paths.
  • If the user is on a route like /dashboard or /profile inside the application, refreshing the page prompts the server to look for that specific resource. Since it only holds the original HTML file, the server might not know how to handle that URL.

 
A Look at Code Snippets to Illustrate the Concept
 

  • Imagine you have JavaScript code managing routes in an SPA. This code might look something like the following:
  • 
    function navigate(path) {
      // Client-side routing handling the view change
      window.history.pushState({}, '', path);
      renderView(path);
    }
      
  • Because the routing happens on the client side, when you refresh the page, the browser asks the server for, say, /profile and the server doesn’t have a file or handler for /profile:
  • 
    // Server receives a request for /profile during a page refresh
    // But it might be expecting to serve only index.html for the SPA
    app.get('/profile', (req, res) => {
      // The server does not know how to handle /profile specifically
      res.status(404).send('Not Found');
    });
      

 
Why Refresh Causes Problems in SPAs
 

  • The problem arises because SPAs divide the responsibility: the browser and JavaScript control navigation while the server simply provides the base page. On refresh, the server is asked to serve a precise URL that it wasn’t specifically told to handle.
  • This mismatch in handling routes means that routes existing only on the client side will not be found by the server, and that is why navigation through direct URL requests or page refreshes can lead to failures or error messages.

How to Fix SPA Routing Issues on Refresh in Lovable

 
Step: Creating a Server File with a Fallback Route
 

  • Create a new file named server.js in your project’s root directory. This file will serve as the entry point for your Express server.
  • Copy and paste the following code inside server.js. This code will serve your static files and ensure that any route not found returns your SPA’s index.html file.
    
    const path = require('path');
    const express = require('express');
    const app = express();
    
    

    // Serve static files from the 'build' directory (adjust if your folder name is different)
    app.use(express.static(path.join(__dirname, 'build')));

    // Fallback route: for any request that doesn't match a static file, serve index.html
    app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname, 'build', 'index.html'));
    });

    // Start the server on the port provided by Lovable or default to 3000
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => {
    console.log(Server is listening on port ${PORT});
    });




  • This fallback route (app.get('*', ...)) is key to fixing SPA routing issues on refresh. It makes sure that if a user refreshes the page on a route like /about, the server sends index.html so your client-side router can handle it.

 
Step: Adding Dependencies Without a Terminal
 

  • Since Lovable does not have a terminal for dependency installation, you need to tell Lovable which packages your application depends on. Open (or create if it doesn’t exist) the package.json file in your project’s root directory.
  • Add the following dependencies section in your package.json file to include Express. Ensure your file now contains something similar to this:
    
    {
      "name": "lovable-spa",
      "version": "1.0.0",
      "main": "server.js",
      "dependencies": {
        "express": "^4.17.1"
      },
      "scripts": {
        "start": "node server.js"
      }
    }
        
  • By adding these lines, Lovable will know to install Express automatically when you deploy your project.

 
Step: Configuring Your Build Process and Deployment
 

  • Make sure your client-side Single Page Application (SPA) is built and the output is placed in a folder named build. If your build folder is named differently, update the path in the server.js file accordingly.
  • Ensure that your SPA’s routing library (such as React Router, Vue Router, etc.) is set to use browser history mode. This mode relies on the HTML5 History API and works correctly when the server is configured to always serve index.html as shown above.
  • When you deploy your project on Lovable, the start script defined in package.json (node server.js) will be executed by Lovable automatically. This starts your Express server with the fallback routing in place.

 
Step: Testing the Changes
 

  • Visit different routes in your application. Try navigating to a nested route like /profile and then refreshing the browser. Without the fallback route, you might receive a “Page not found” error; with these changes, your route should work correctly.
  • If you experience any issues, double-check that the paths in server.js match your project structure. For example, ensure the build folder exists and contains the latest version of index.html.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Best Practices for Configuring SPA Routing in Lovable

 
Defining Your Routing Configuration
 

  • Create a new file in your Lovable project called routes.js. This file will contain all the information about which parts of your webpage show up for different URL paths.
  • Inside routes.js, add the following code snippet. This code tells Lovable what to do when it sees an address like "/" for the homepage, "/about" for the about page, and so on. Notice the last route (path: '\*'), which makes sure any address not defined will point back to your main page. Simply copy and paste this code into routes.js:
    <pre><code class="hljs">
    // This is your routing configuration for the SPA
    const routes = [
      {
        path: '/',
        component: 'HomeComponent', // Replace with your Homepage component
      },
      {
        path: '/about',
        component: 'AboutComponent', // Replace with the About page component
      },
      {
        path: '/contact',
        component: 'ContactComponent', // Replace with the Contact page component
      },
      {
        // This wildcard route directs any unknown URLs back to the homepage.
        path: '\*',
        redirect: '/'
      }
    ];
    
    // Export the routes so that other files can use them
    export default routes;
    </code></pre>
    
  • This file helps Lovable know which parts of your application to load when users click on different links, ensuring a smooth, single-page experience.

 
Integrating the Router into Your Main Code
 

  • Find your main application file. In Lovable projects this is often named something like main.js or app.js. Open that file in the code editor.
  • At the top of the file, import the router configuration you just created. Then set up the router. Since Lovable does not have a terminal for installing dependencies, add the necessary code directly into the file. For example, add this snippet at the top of your main file:
    <pre><code class="hljs">
    // Import the routing configuration from routes.js
    import routes from './routes';
    
    // Create a simple router using Lovable's built-in router constructor
    // (Assuming Lovable provides a router class named 'Router')
    const router = new Router({
      routes: routes
    });
    </code></pre>
    
  • After setting up the router, ensure you link it with your app's main container or view rendering area. Below is an example snippet where you tell your app to use the created router:
    <pre><code class="hljs">
    // Assume 'app' is your main application object in Lovable
    app.useRouter(router);
    
    // Initialize your application
    app.init();
    </code></pre>
    
  • This integration ensures that when a user clicks on a link or enters a URL manually, Lovable uses your router to display the correct view without reloading the whole page.

 
Implementing Lazy Loading for Components
 

  • To make your app load faster, it is best to load components only when needed. In your routes.js file, you can modify each route to load its component on demand. Update the code like this:
    <pre><code class="hljs">
    const routes = [
      {
        path: '/',
        // Lazy load the HomeComponent when the route is activated
        component: () => import('./components/HomeComponent.js')
      },
      {
        path: '/about',
        component: () => import('./components/AboutComponent.js')
      },
      {
        path: '/contact',
        component: () => import('./components/ContactComponent.js')
      },
      {
        path: '\*',
        redirect: '/'
      }
    ];
    
    export default routes;
    </code></pre>
    
  • Make sure that the components (HomeComponent.js, AboutComponent.js, and ContactComponent.js) exist inside a components directory in your project. If not, create the directory and add your component files there.
  • This approach helps speed up the initial load of your app by loading only what is needed for the current view.

 
Troubleshooting Routing Issues
 

  • If an unexpected error occurs, first check that the paths in your routes.js file match exactly what you have in your links and that no typos exist.
  • Make sure that the wildcard route (path: '\*') is the last entry, as Lovable processes routes in the order they are defined.
  • If components do not load correctly, verify that the file paths provided in the import statements are correct and that the component files export what Lovable needs.
  • Remember: since Lovable does not provide a terminal, all dependency changes must be added as code within your files. Check that your main file correctly imports and initialises the router without any missing or extra code.

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022