How to Build a Store Locator with Python and Flask
This guide walks you through creating a simple but powerful store locator. We'll build a Flask backend that uses the Payloadic ZIP Code API to find locations within a radius and a Leaflet.js frontend to display them on a map.
What You'll Build
You'll create a web page with a search box where a user can enter a ZIP code. The frontend will call your Flask API, which in turn queries the Payloadic ZIP Code API to get a list of ZIP codes within the specified radius. Your API then finds stores in those ZIP codes and returns them to the frontend to be displayed on an interactive map and in a list.
Project Structure
Our Flask application will have a simple structure. The Python code runs the server, which serves an HTML page and provides the API endpoint for searching stores.
store-locator/
├── app.py # The Flask backend
└── templates/
└── index.html # The HTML frontend
└── static/
└── script.js # The frontend JavaScript logicfrom flask import Flask, render_template, request, jsonify
from dotenv import load_dotenv
import os
import requests
load_dotenv()
app = Flask(__name__)
# In-memory store data (replace with a database in a real application)
STORES = [
{"id": 1, "name": "San Francisco Central", "lat": 37.7749, "lng": -122.4194, "address": "123 Market St"},
{"id": 2, "name": "Palo Alto Tech", "lat": 37.4419, "lng": -122.1430, "address": "456 University Ave"},
{"id": 3, "name": "Oakland Lakeside", "lat": 37.8044, "lng": -122.2712, "address": "789 Broadway"},
{"id": 4, "name": "San Jose Downtown", "lat": 37.3382, "lng": -121.8863, "address": "101 S First St"},
{"id": 5, "name": "Berkeley Campus", "lat": 37.8715, "lng": -122.2730, "address": "200 Telegraph Ave"}
]
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/stores')
def get_stores():
zipcode = request.args.get('zipcode')
radius = request.args.get('radius', 10) # Default radius 10 miles
if not zipcode:
return jsonify({"error": "A start ZIP code is required."}),
api_key = os.getenv('RAPIDAPI_API_KEY')
if not api_key:
return jsonify({"error": "API key is not configured."}),
# Get ZIP codes within radius from Payloadic API
try:
url = "https://zip-code-api8.p.rapidapi.com/radius"
querystring = {"zipcode": zipcode, "radius": str(radius)}
headers = {
"X-RapidAPI-Key": api_key,
"X-RapidAPI-Host": "zip-code-api8.p.rapidapi.com"
}
response = requests.get(url, headers=headers, params=querystring)
response.raise_for_status()
data = response.json()
# In a real app, you'd use the returned ZIP codes to query your database.
# For this example, we'll just return our mock stores if the API call is successful.
# This simulates finding nearby stores.
# Add a 'distance' key to each store for the frontend
for i, store in enumerate(STORES):
# This is mock distance. In a real app, you'd get this from the ZIP Code API response.
STORES[i]['distance'] = (i + 1) * 2.5
return jsonify(STORES)
except requests.exceptions.RequestException as e:
return jsonify({"error": str(e)}),
except Exception as e:
return jsonify({"error": "An internal error occurred."}),
if __name__ == '__main__':
app.run(debug=True, port=5001)
Backend: Flask API (app.py)
The Flask app has two main parts: a route to serve the index.html file and an /api/stores endpoint. When the API endpoint is called, it fetches ZIP codes within a radius from the Payloadic API and then returns a list of matching stores. For simplicity, our stores are hard-coded, but in a real application, you would query your database for stores in the returned ZIP codes.
Frontend: HTML & Leaflet.js (index.html & script.js)
The frontend consists of a simple HTML page that includes a search form and a map container from Leaflet.js. The JavaScript file handles the form submission, makes a fetch request to our Flask backend, and then dynamically populates the map with markers and updates the store list based on the JSON response.