Files
justvitamin/app.py
Omair Saleh 09d837a660 v2: Live Flask app — real Gemini AI demos, Nano Banana image gen, real £19.4M data dashboard
- Flask + gunicorn backend replacing static nginx
- 3 live AI demos powered by Gemini 2.5 Flash
- Nano Banana + Nano Banana Pro for product image generation
- Real JV ecommerce dashboard (728K orders, 230K customers, 4MB data)
- AI Infrastructure Proposal + Offer pages
- Live product scraper for justvitamins.co.uk + competitor pages
- API: /api/scrape, /api/generate-pack, /api/competitor-xray, /api/pdp-surgeon, /api/generate-images
2026-03-02 20:02:25 +08:00

195 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""JustVitamin × QuikCue — AI Content Engine
Live proposal site with real Gemini-powered demos."""
import os, json, time, traceback
from pathlib import Path
from flask import (Flask, render_template, jsonify, request,
send_from_directory, redirect)
from scraper import scrape_product, scrape_competitor
from ai_engine import (generate_asset_pack, competitor_xray, pdp_surgeon,
optimise_pdp_copy, generate_product_images)
app = Flask(__name__,
static_folder="static",
template_folder="templates")
GEN_DIR = Path(__file__).parent / "generated"
GEN_DIR.mkdir(exist_ok=True)
# ── Page routes ──────────────────────────────────────────────
@app.route("/")
def index():
return render_template("index.html")
@app.route("/dashboard")
def dashboard():
return send_from_directory("static/dashboard", "index.html")
@app.route("/dashboard/jv_data.json")
def dashboard_data():
return send_from_directory("static/dashboard", "jv_data.json")
@app.route("/proposal")
def proposal():
return send_from_directory("static/proposal", "index.html")
@app.route("/offer")
def offer():
return send_from_directory("static/offer", "index.html")
@app.route("/generated/<path:filename>")
def serve_generated(filename):
return send_from_directory(GEN_DIR, filename)
# ── API: Scrape ──────────────────────────────────────────────
@app.route("/api/scrape", methods=["POST"])
def api_scrape():
"""Scrape a JustVitamins product page."""
url = request.json.get("url", "").strip()
if not url:
return jsonify({"error": "No URL provided"}), 400
try:
data = scrape_product(url)
if not data.get("title"):
return jsonify({"error": "Could not find product. Check URL."}), 400
return jsonify(data)
except Exception as e:
traceback.print_exc()
return jsonify({"error": str(e)}), 500
@app.route("/api/scrape-competitor", methods=["POST"])
def api_scrape_competitor():
"""Scrape any competitor product page."""
url = request.json.get("url", "").strip()
if not url:
return jsonify({"error": "No URL provided"}), 400
try:
data = scrape_competitor(url)
if not data.get("title"):
return jsonify({"error": "Could not extract product data."}), 400
return jsonify(data)
except Exception as e:
traceback.print_exc()
return jsonify({"error": str(e)}), 500
# ── API: Demo A — 12-Asset Pack ──────────────────────────────
@app.route("/api/generate-pack", methods=["POST"])
def api_generate_pack():
"""Generate a full 12-asset marketing pack from product data."""
product = request.json
if not product:
return jsonify({"error": "No product data"}), 400
try:
t0 = time.time()
pack = generate_asset_pack(product)
pack["_generation_time"] = f"{time.time()-t0:.1f}s"
pack["_product_title"] = product.get("title", "")
return jsonify(pack)
except Exception as e:
traceback.print_exc()
return jsonify({"error": str(e)}), 500
# ── API: Demo B — Competitor X-Ray ───────────────────────────
@app.route("/api/competitor-xray", methods=["POST"])
def api_competitor_xray():
"""Scrape competitor + run AI analysis."""
url = request.json.get("url", "").strip()
if not url:
return jsonify({"error": "No URL provided"}), 400
try:
t0 = time.time()
comp_data = scrape_competitor(url)
if not comp_data.get("title"):
return jsonify({"error": "Could not scrape competitor page."}), 400
analysis = competitor_xray(comp_data)
analysis["_scrape_data"] = {
"title": comp_data.get("title"),
"price": comp_data.get("price"),
"brand": comp_data.get("brand"),
"url": url,
}
analysis["_generation_time"] = f"{time.time()-t0:.1f}s"
return jsonify(analysis)
except Exception as e:
traceback.print_exc()
return jsonify({"error": str(e)}), 500
# ── API: Demo C — PDP Surgeon ────────────────────────────────
@app.route("/api/pdp-surgeon", methods=["POST"])
def api_pdp_surgeon():
"""Rewrite PDP copy in a given style."""
data = request.json or {}
product = data.get("product")
style = data.get("style", "balanced")
if not product:
return jsonify({"error": "No product data"}), 400
try:
t0 = time.time()
result = pdp_surgeon(product, style)
result["_generation_time"] = f"{time.time()-t0:.1f}s"
return jsonify(result)
except Exception as e:
traceback.print_exc()
return jsonify({"error": str(e)}), 500
# ── API: Full PDP Optimise ───────────────────────────────────
@app.route("/api/optimise", methods=["POST"])
def api_optimise():
"""Full PDP rewrite — scrape + AI copy."""
product = request.json
if not product:
return jsonify({"error": "No product data"}), 400
try:
t0 = time.time()
copy = optimise_pdp_copy(product)
copy["_generation_time"] = f"{time.time()-t0:.1f}s"
return jsonify(copy)
except Exception as e:
traceback.print_exc()
return jsonify({"error": str(e)}), 500
# ── API: Image Generation ────────────────────────────────────
@app.route("/api/generate-images", methods=["POST"])
def api_generate_images():
"""Generate AI product images via Nano Banana / Pro."""
product = request.json
if not product:
return jsonify({"error": "No product data"}), 400
try:
t0 = time.time()
images = generate_product_images(product)
images["_generation_time"] = f"{time.time()-t0:.1f}s"
return jsonify(images)
except Exception as e:
traceback.print_exc()
return jsonify({"error": str(e)}), 500
# ── Health check ─────────────────────────────────────────────
@app.route("/api/health")
def health():
return jsonify({
"status": "ok",
"gemini_key_set": bool(os.environ.get("GEMINI_API_KEY")),
})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5050, debug=True)