/how-to-build-lovable

How to build Food delivery backend with Lovable?

Build a robust food delivery backend with Lovable. Follow our step-by-step guide to design a scalable, efficient system for seamless, reliable service.

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

How to build Food delivery backend with Lovable?

 
Project Setup and File Creation
 

  • Create a new Lovable project.
  • Create a file named main.py. This file will contain all the backend code for our food delivery service.
  • Create a file named orders.json in the project’s root directory. This file will act as a simple database to store orders. Open orders.json and insert an empty JSON array:
    
    []
        
  • Because Lovable does not support a terminal for dependency installation, add the following code snippet at the top of your main.py file to automatically install Flask (if not already installed):
    
    import sys
    try:
        from flask import Flask, request, jsonify, abort
    except ImportError:
        import subprocess
        subprocess.check\_call([sys.executable, "-m", "pip", "install", "flask"])
        from flask import Flask, request, jsonify, abort
        

 
Setting Up the Backend Server and API Endpoints
 

  • In main.py, set up the Flask server and create helper functions for reading and writing orders. Insert this code below the dependency installation snippet:
    
    import json
    
    

    app = Flask(name)

    def read_orders():
    with open('orders.json', 'r') as f:
    return json.load(f)

    def write_orders(orders):
    with open('orders.json', 'w') as f:
    json.dump(orders, f)



  • Add an API endpoint to create a new food order (HTTP POST). Insert the following code right after the helper functions:

    @app.route('/order', methods=['POST'])
    def create_order():
    order = request.get_json()
    orders = read_orders()
    orders.append(order)
    write_orders(orders)
    return jsonify(order), 201


  • Add an endpoint to retrieve all orders (HTTP GET). Place this code after the create_order endpoint:

    @app.route('/orders', methods=['GET'])
    def get_orders():
    orders = read_orders()
    return jsonify(orders)


  • At the end of the file, include the server startup command so Lovable can run your backend:

    if name == 'main':
    app.run(host='0.0.0.0', port=5000)

 
Incorporating Basic Authentication for Security
 

  • For secure endpoints, add a simple API key mechanism. Append the following helper function in main.py (for example, just after the previous endpoints):
    
    from functools import wraps
    
    

    def require_api_key(f):
    @wraps(f)
    def decorated(_args, _*kwargs):
    if request.headers.get('x-api-key') != 'YOUR_API_KEY':
    abort(401)
    return f(_args, _*kwargs)
    return decorated



  • Create a new secure endpoint for order creation using the API key. Insert this code snippet below the existing endpoints:

    @app.route('/secure_order', methods=['POST'])
    @require_api_key
    def secure_create_order():
    order = request.get_json()
    orders = read_orders()
    orders.append(order)
    write_orders(orders)
    return jsonify(order), 201


  • Remember to replace YOUR_API_KEY with a secret key of your choice.

 
Testing and Debugging Your Food Delivery Backend
 

  • To test your endpoints, use Lovable’s built-in preview tool. Once you click the Run button, Lovable will start your server on port 5000.
  • You can verify the functionality by sending a POST request to /order with a JSON payload. For example, you can use Lovable’s HTTP request simulation feature or an external tool like Postman.
  • Test the GET endpoint by accessing /orders via a browser or API client to see the list of created orders.
  • If you use the secure endpoint /secure\_order, ensure you include the header x-api-key with the correct key in your request.

 
Deploying and Iterating on Your Backend
 

  • Every time you make changes to any file, save the changes in Lovable’s editor.
  • Click the Run button to restart your backend and apply the changes.
  • Monitor the Lovable console for any error messages which will help in debugging issues.
  • Once satisfied with the functionality, share your project’s URL (provided by Lovable) with testers or integrate it with your front-end application.

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

How to Set Up Order Status Updates in Your Food Delivery Backend


const express = require('express');
const mongoose = require('mongoose');
const app = express();

app.use(express.json());

mongoose.connect('mongodb://localhost:27017/fooddelivery', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

const OrderSchema = new mongoose.Schema({
  restaurantId: { type: mongoose.Schema.Types.ObjectId, ref: 'Restaurant' },
  items: [{
    foodId: mongoose.Schema.Types.ObjectId,
    quantity: Number
  }],
  status: {
    type: String,
    enum: ['pending', 'preparing', 'delivering', 'completed'],
    default: 'pending'
  },
  createdAt: { type: Date, default: Date.now }
});

const Order = mongoose.model('Order', OrderSchema);

app.put('/api/orders/:id/status', async (req, res) => {
  try {
    const { status } = req.body;
    if (!['pending', 'preparing', 'delivering', 'completed'].includes(status)) {
      return res.status(400).json({ error: 'Invalid status value' });
    }
    const order = await Order.findByIdAndUpdate(
      req.params.id,
      { status },
      { new: true }
    );
    if (!order) {
      return res.status(404).json({ error: 'Order not found' });
    }
    res.json(order);
  } catch (err) {
    res.status(500).json({ error: 'Server error' });
  }
});

app.listen(3000, () => {
  console.log('Food delivery backend running on port 3000');
});

How to Create a Delivery Estimate Endpoint for Your Food Delivery Backend


const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());

const MAPBOX_API_TOKEN = 'your_mapbox_api\_token';

app.get('/api/delivery/estimate', async (req, res) => {
  try {
    const { origin, destination } = req.query;
    if (!origin || !destination) {
      return res.status(400).json({ error: 'Both origin and destination coordinates are required in "longitude,latitude" format.' });
    }
    const url = `https://api.mapbox.com/directions/v5/mapbox/driving/${origin};${destination}?access_token=${MAPBOX_API_TOKEN}&geometries=geojson`;
    const response = await axios.get(url);
    if (response.data && response.data.routes && response.data.routes.length > 0) {
      const { distance, duration } = response.data.routes[0];
      return res.json({ distance, duration });
    }
    res.status(500).json({ error: 'Unable to retrieve route data' });
  } catch (error) {
    res.status(500).json({ error: 'Server error' });
  }
});

app.listen(4000, () => {
  console.log('Food delivery backend API is running on port 4000');
});

How to Split Orders into Restaurant Sub-Orders Using Lovable


const express = require('express');
const mongoose = require('mongoose');
const app = express();

app.use(express.json());

const OrderSchema = new mongoose.Schema({
  customerId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
  items: [
    {
      restaurantId: { type: mongoose.Schema.Types.ObjectId, ref: 'Restaurant' },
      foodId: { type: mongoose.Schema.Types.ObjectId, ref: 'Food' },
      quantity: Number
    }
  ],
  status: {
    type: String,
    enum: ['pending', 'assigned', 'split', 'delivering', 'completed'],
    default: 'pending'
  },
  createdAt: { type: Date, default: Date.now }
});

const Order = mongoose.model('Order', OrderSchema);

app.post('/api/orders/split', async (req, res) => {
  try {
    const { customerId, items } = req.body;
    if (!customerId || !items || !Array.isArray(items) || items.length === 0) {
      return res.status(400).json({ error: 'Invalid order data' });
    }

    // Group items by their restaurantId
    const ordersByRestaurant = items.reduce((acc, item) => {
      const key = item.restaurantId;
      if (!acc[key]) {
        acc[key] = [];
      }
      acc[key].push({
        foodId: item.foodId,
        quantity: item.quantity
      });
      return acc;
    }, {});

    // Create sub-orders for each restaurant
    const createdOrders = [];
    for (const restaurantId in ordersByRestaurant) {
      const orderData = {
        customerId,
        items: ordersByRestaurant[restaurantId].map((item) => ({
          restaurantId,
          ...item
        })),
        status: 'pending'
      };
      const subOrder = new Order(orderData);
      await subOrder.save();
      createdOrders.push(subOrder);
    }

    res.status(201).json({
      message: 'Order has been split into sub-orders successfully.',
      orders: createdOrders
    });
  } catch (error) {
    res.status(500).json({ error: 'Server error while splitting order.' });
  }
});

mongoose.connect('mongodb://localhost:27017/fooddelivery', {
  useNewUrlParser: true,
  useUnifiedTopology: true
})
.then(() => {
  app.listen(5000, () => {
    console.log('Food delivery backend running on port 5000');
  });
})
.catch((err) => {
  console.error('Database connection error:', err);
});

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
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

Best Practices for Building a Food delivery backend with AI Code Generators

 
Planning the Food Delivery Backend System
 

  • Define the core features: user registration and authentication, restaurant listings, menu management, order processing, payment integration, driver assignment, and real-time order tracking.
  • Decide on the technology stack, such as using Python with frameworks like Flask or Django, or Node.js with Express, along with a choice of SQL or NoSQL databases.
  • Outline non-functional requirements: scalability, security, performance, and future integration of AI-driven features.

 
Designing the System Architecture
 

  • Plan a modular architecture including separate modules for user management, order processing, restaurant management, and notifications.
  • Define clear API endpoints that will allow communication between front-end applications and the backend services.
  • Use a microservices approach if needed, to easily scale and integrate independent services like payment handling and driver tracking.
  • Decide on data storage strategies: a relational database for transactional data and a NoSQL database for session or real-time data.

 
Integrating AI Code Generators
 

  • Select an AI code generator tool that supports your programming language (for example, GitHub Copilot or OpenAI Codex) to help generate boilerplate code for API endpoints, models, and tests.
  • Configure your development environment to work with the AI tool by installing necessary extensions or plugins in your IDE.
  • Leverage AI-powered suggestions to build repetitive structures like CRUD operations, and then manually review and customize the generated code as needed.
  • Create a sample AI-assisted file, for example an integration helper:
    
    # ai\_generator.py
    def generate_endpoint_code(endpoint\_name, method):
        # This is a stub function that an AI generator might help populate
        code\_template = f'''
    @app.route('/{endpoint\_name}', methods=['{method.upper()}'])
    def {endpoint\_name}():
        # Implement the {endpoint\_name} functionality
        return jsonify({{"status": "success", "message": "Endpoint {endpoint\_name} reached"}})
    '''
        return code\_template
    
    

    if name == 'main':
    print(generate_endpoint_code("order", "post"))


 
Developing Backend Endpoints
 

  • Set up your backend framework to handle API requests. For instance, if you use Flask, initialize your application and define routes to handle operations like order placement and order tracking.
  • Use AI code generators to create consistent API structures. Review each generated endpoint to ensure security and business logic compliance.
  • Example of a simple Flask endpoint:
    
    from flask import Flask, request, jsonify
    
    

    app = Flask(name)

    @app.route('/create_order', methods=['POST'])
    def create_order():
    order_data = request.get_json()
    # Validate and process the order data here
    return jsonify({"status": "success", "order_id": 123})

    if name == 'main':
    app.run(host='0.0.0.0', port=5000)


 
Configuring the Database
 

  • Choose the appropriate database system (e.g., PostgreSQL, MySQL, or MongoDB) based on your data and scaling requirements.
  • Define data models for entities like Users, Orders, Restaurants, and Drivers. Use Object Relational Mapping (ORM) tools for easier database management.
  • Example using SQLAlchemy for a food delivery order model:
    
    from flask\_sqlalchemy import SQLAlchemy
    
    

    db = SQLAlchemy()

    class Order(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    customer_id = db.Column(db.Integer, nullable=False)
    restaurant_id = db.Column(db.Integer, nullable=False)
    total_amount = db.Column(db.Float, nullable=False)
    status = db.Column(db.String(50), default='Pending')


 
Implementing Security Best Practices
 

  • Ensure secure user authentication and token management using libraries such as Flask-JWT-Extended or Passport.js for Node.js.
  • Use HTTPS to encrypt data in transit, and store sensitive data in an encrypted format.
  • Regularly audit and update dependencies to minimize vulnerabilities, and follow coding standards recommended by security best practices.

 
Testing and Debugging Using AI Tools
 

  • Write unit and integration tests for each component of your backend. Use AI-assisted tools to generate test cases faster.
  • Integrate automated testing frameworks like PyTest or Mocha/Chai to continuously test each endpoint.
  • Example of a simple PyTest test case for the Flask endpoint:
    
    import pytest
    from app import app
    
    

    @pytest.fixture
    def client():
    app.testing = True
    with app.test_client() as client:
    yield client

    def test_create_order(client):
    response = client.post('/create_order', json={'customer_id': 1, 'restaurant_id': 2, 'total_amount': 29.99})
    json_data = response.get_json()
    assert json_data['status'] == 'success'


 
Deployment and Maintenance
 

  • Plan your deployment by choosing a reliable cloud provider like AWS, Google Cloud, or Heroku that supports scaling based on demand.
  • Containerize your application using Docker for consistent deployment environments and easier rollbacks.
  • Create a Dockerfile for your application:
    
    # Dockerfile
    FROM python:3.9-slim
    
    

    WORK

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