Passenger (cPanel)
    ↓
Flask app
    ↓
filter_recipes()
    ↓
runtime_recipes.json

 

control panel

[ Include ingredients ]
[ Exclude ingredients ]  

We don’t have to invent anything new. Just surface it. 

/query?include=bean&exclude=corn

 

Drop this into your Flask app (same level as your API or separate if you want clean separation):

from flask import Flask, request, render_template_string
import requests

app = Flask(__name__)

API_URL = "http://127.0.0.1:5000/query"

HTML = """
<!doctype html>
<title>Get Smart</title>
<h2>Get Smart 🍳</h2>

<form method="post">
  <label>Include ingredients:</label><br>
  <input type="text" name="include" placeholder="e.g. beans, rice"><br><br>

  <label>Exclude ingredients:</label><br>
  <input type="text" name="exclude" placeholder="e.g. corn"><br><br>

  <button type="submit">Find Recipes</button>
</form>

{% if results %}
  <h3>Results</h3>
  <ul>
  {% for r in results %}
    <li>{{ r['title'] }}</li>
  {% endfor %}
  </ul>
{% endif %}
"""

@app.route("/", methods=["GET", "POST"])
def index():
    results = []

    if request.method == "POST":
        include = request.form.get("include", "")
        exclude = request.form.get("exclude", "")

        params = {}
        if include:
            params["include"] = include
        if exclude:
            params["exclude"] = exclude

        r = requests.get(API_URL, params=params)
        if r.ok:
            results = r.json().get("results", [])

    return render_template_string(HTML, results=results)

if __name__ == "__main__":
    app.run(debug=True)

🧠 Why this fits your architecture

  • Backdrop → still your source (recipes JSON)
  • Gateway (Flask API) → already filtering correctly
  • This UI → just a translator of human → query params

No logic added
No intelligence wasted
No rule duplication

Exactly your rule:

Don’t spend intelligence where you already have enough.


🧪 What this gives you immediately

  • Type: beans
  • Exclude: corn
  • Click button
  • You hit your existing engine

You’ve just built:

a deterministic human → contract → system bridge


🔜 Next step (don’t do it yet, just note it)

When you're ready:

  • split comma input → list normalization
  • add AND vs OR behavior
  • maybe add “contains ANY / ALL” toggle

But right now?

👉 You have a working input door.
👉 It speaks your contract.
👉 It does not improvise.


If you want, next step we can:
lock input normalization at the Gateway level so UI stays dumb and safe.