/lovable-issues

Fixing Production Issues Not Present in Lovable Local Preview

Explore why Lovable production builds differ from previews, fix production issues, and apply best practices for stability.

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 Production Builds Fail Differently Than Previews in Lovable

 
Understanding Build Environments
 
In a preview or development environment, the application is run with extra checks, detailed error messages, and debugging tools. These tools help developers quickly identify errors while coding. In contrast, production builds aim to run more smoothly and efficiently. This efficiency often comes from removing these extra tools and applying optimizations. Because of this, something that might work in a preview can fail in production if the code depends on details available only in development.


/_ Example of a development configuration _/
const config = {
    debug: true,
    logLevel: 'verbose',
    environment: 'development',
};

 
Differences in Optimizations
 
In production, the build process usually includes optimizations like code minification and the removal of unused code. These steps make the application smaller and faster, but they may also hide issues. For instance, variable names might get shortened or some code might be removed if it's thought to be unnecessary. This can cause parts of the application to behave differently if there are hidden dependencies or if the code was not written in a way that supports such transformations.


// Before optimization in development
function calculateValue(input) {
    const multiplier = 2;
    return input \* multiplier;
}

// After minification in production, variable names may change
function a(b){return b\*2;}

 
Environment Variables and Configurations
 
Applications often rely on settings that are provided by environment variables. In a preview, these variables might be set to give maximum information, while in production the values could be completely different. For example, an API endpoint or a secret key might be set to a testing value during preview. When the application is built for production, these configurations are replaced with the actual values. If the application was inadvertently dependent on the development configuration settings, it might fail when running in production.


// Development settings
const apiUrl = process.env.API\_URL || 'http://localhost:3000';

// Production settings use a different environment variable
const apiUrl = process.env.API\_URL;

 
Different Modules and Code Splitting
 
Another reason for the differences in behavior is how modules and assets are bundled. In previews, everything might be loaded together, so any missing or disorganized piece of code might not be immediately noticeable. Production builds often split code into smaller parts and load them only when needed. If some of these parts are not correctly referenced or ordered, the production version can fail even if the development preview worked properly.


// Example showing code splitting in production builds
// Development: all code is bundled together
import { featureA, featureB } from './features';

// Production: code splitting might separate these features
loadModule('./features').then(features => {
    features.featureA();
});

How to Fix Production-Only Issues in Lovable Builds

 
Step One: Create Global Error Handlers
 

  • In your main JavaScript file (for example, index.js), add the following code near the top. This code will catch unexpected errors that occur only in production:
    
    function logError(err) {
      // This will log production errors for later review.
      console.error('Production Error Detected:', err);
    }
    
    

    process.on('uncaughtException', logError);
    process.on('unhandledRejection', logError);



  • This code makes sure that any errors are captured and logged, helping you diagnose issues that only appear when running in production.

 
Step Two: Set Up a Production Configuration File
 

  • Create a new file named production.json in your project. This file will store production-specific settings.
    
    {
      "env": "production",
      "debug": false,
      "logging": {
        "level": "error"
      }
    }
        
  • This file tells your application it’s running in production mode and adjusts settings like debugging and logging levels accordingly.

 
Step Three: Load the Production Configuration
 

  • Create or open your configuration loader script (for instance, config.js). Insert the following code so your app can read production.json:
    
    var fs = require('fs');
    
    

    try {
    var config = JSON.parse(fs.readFileSync('production.json', 'utf8'));
    if (config.env === 'production') {
    // Set environment-specific variables.
    process.env.NODE_ENV = 'production';
    process.env.DEBUG = config.debug;
    }
    } catch (err) {
    console.error('Error reading production configuration:', err);
    }



  • This ensures your application loads and applies production settings every time it starts.

 
Step Four: Embed a Logging Dependency Manually
 

  • Since Lovable doesn’t have a terminal to install dependencies, you should include the needed logging functionality directly into your project.
  • Create a new file named winston.js inside a folder called dependencies (create the folder if it doesn’t exist). Paste the following minimal logging code:
    
    // This is a simplified version of a logging library.
    var winston = {
      log: function(level, msg) {
        if (level === 'error') {
          console.error('Logged Error:', msg);
        }
      }
    };
    
    

    module.exports = winston;



  • Now, in your main application file (for example, index.js), import this logging module with:

    var winston = require('./dependencies/winston');

 
Step Five: Implement Production-Specific Error Handling Middleware
 

  • If your application handles requests (for example, using Express), add production-specific error responses. In your error handling middleware, use the following code:
    
    function handleError(err, req, res, next) {
      if (process.env.NODE\_ENV === 'production') {
        // Respond with a generic message and log the detailed error.
        res.status(500).send('An error occurred. Please try again later.');
        winston.log('error', err.stack);
      } else {
        // In non-production, you might want to see the full error stack.
        res.status(500).send(err.stack);
      }
    }
        
  • Place this middleware after all other routes in your main file to catch errors during request processing.

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 Ensuring Production Stability in Lovable

 
Enhancing Logging for Production Stability
 

  • In your main project directory for Lovable, create a new file named logger.py. This file will help you record what happens in your application so you can understand issues later.
  • Add the following snippet to logger.py. This code sets up a logging system that saves messages to a file, which is very useful when your production code runs without a visible terminal:
    • 
      import os
      import datetime
      
      

      def log_message(message, level="INFO"):
      log_dir = "logs"
      if not os.path.exists(log_dir):
      os.makedirs(log_dir)
      today = datetime.date.today().strftime("%Y-%m-%d")
      log_file = os.path.join(log_dir, f"{today}.log")
      with open(log_file, "a") as f:
      timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
      f.write(f"[{timestamp}] [{level}] {message}\n")




  • In your main code file (for example, main.py), import this logger by adding at the very top:




    • from logger import log_message



  • Use the function log_message throughout your code wherever you want to record important events or errors.

 
Implementing Robust Error Handling
 

  • Navigate to the parts of your code where errors might occur. Wrap these sections with a try/except block to catch exceptions. This practice prevents the application from crashing by handling errors gracefully.
  • Insert the following snippet within your functional logic. For instance, in main.py, around any call that might throw an error:
    • 
      try:
          # Your normal processing code here, e.g. connecting to a database or processing user input
          process_user_data()
      except Exception as e:
          log\_message(f"Error occurred: {str(e)}", level="ERROR")
          # Optionally, you may add additional error handling or fallback mechanisms here
            
  • This method logs the error and allows your program to continue running or to perform a controlled shutdown.

 
Setting Up Production Configurations
 

  • Create a new file in your project directory called production\_config.py. This file will hold settings that define how your code runs in production, such as debugging flags or connection parameters.
  • Add this snippet to production\_config.py to separate production settings from development ones:
    • 
      production\_config.py
      
      

      DEBUG = False
      DATABASE_URI = "your-production-database-uri"
      LOG_LEVEL = "INFO"




  • In your main code file, import this configuration. At the very beginning of main.py, add:




    • from production_config import DEBUG, DATABASE_URI, LOG_LEVEL



  • Now your code can adjust its behavior via these configurable parameters to ensure stability in production.

 
Introducing Monitoring and Health Checks
 

  • It is important to know if your application is running correctly. Create a new file called health\_check.py in your project directory.
  • Insert the following code snippet in health\_check.py to create a basic health check endpoint that can be monitored:
    • 
      def health():
          try:
              # Perform simple checks such as file access or database connection here
              status = "OK"
          except Exception:
              status = "FAIL"
          return status
      
      

      if name == "main":
      # This allows testing the endpoint manually if needed
      result = health()
      print(f"Application Health: {result}")




  • In your main code, if you have an HTTP server, consider adding an endpoint (for instance, /health) that calls the health() function. This makes it easier for monitoring tools to check the system’s status.

 
Automating Dependency Management Without a Terminal
 

  • Because Lovable does not provide terminal access, you must ensure that required libraries are automatically available. Insert code at the start of your main file (main.py) to check and install missing dependencies.
  • Add the following snippet at the very beginning of main.py:
    • 
      import importlib
      import subprocess
      import sys
      
      

      def install_if_missing(package):
      try:
      importlib.import_module(package)
      except ImportError:
      subprocess.check_call([sys.executable, "-m", "pip", "install", package])

      Example: Ensure the 'requests' library is installed
      install_if_missing("requests")




  • This code checks for the presence of a library (like requests) and installs it if missing, ensuring your production code has all dependencies it needs.

 
Setting Up Automated Recovery and Alerts
 

  • Set up a simple mechanism in your main code to automatically alert you and attempt recovery when a serious error occurs. For example, in main.py, after logging a critical error, send an alert using a basic email function.
  • Create a file called alerts.py with the following content:
    • 
      import smtplib
      
      

      def send_alert(message):
      # Set up your email server configuration here
      server = smtplib.SMTP("smtp.example.com", 587)
      server.starttls()
      server.login("your-email@example.com", "your-password")
      subject = "Production Alert"
      body = f"Subject: {subject}\n\n{message}"
      server.sendmail("your-email@example.com", "alert-recipient@example.com", body)
      server.quit()




  • Then, in main.py, you can call this alert function when a critical issue is caught:




    • from alerts import send_alert

      try:
      critical_task()
      except Exception as e:
      log_message(f"Critical failure: {str(e)}", level="CRITICAL")
      send_alert(f"Critical failure encountered: {str(e)}")




  • This ensures that you are informed quickly and can take action, increasing the stability of your production environment.

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