From d518beb637e7c2776d84e87c63cc201c101ca89c Mon Sep 17 00:00:00 2001 From: JJ Date: Sun, 30 Mar 2025 20:56:01 +0100 Subject: styling, sub instructions --- .gitignore | 1 + requirements.txt | 21 + scripts/database/mongo.py | 12 +- scripts/recipes/handle_recipes.py | 9 +- scripts/scraping/scraper.py | 84 +- scripts/users/handle_users.py | 18 +- server.py | 61 +- static/images/bars.svg | 52 + static/scripts/htmx-targets.js | 129 ++ static/scripts/index.js | 11 + static/style/style.css | 27 +- templates/base.html | 9 +- templates/components/app.html | 6 +- templates/pages/account.html | 19 +- templates/pages/home.html | 34 +- templates/pages/signup.html | 2 + templates/pages/single-recipe.html | 12 + veg.html | 3693 ------------------------------------ 18 files changed, 419 insertions(+), 3781 deletions(-) create mode 100644 requirements.txt create mode 100644 static/images/bars.svg create mode 100644 static/scripts/htmx-targets.js create mode 100644 static/scripts/index.js delete mode 100644 veg.html diff --git a/.gitignore b/.gitignore index 62c1b88..e6a7493 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ dist/ htmlcov/ .tox/ docs/_build/ +Constants.py diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f2db2fa --- /dev/null +++ b/requirements.txt @@ -0,0 +1,21 @@ +bcrypt==4.3.0 +beautifulsoup4==4.13.3 +blinker==1.9.0 +certifi==2025.1.31 +charset-normalizer==3.4.1 +click==8.1.8 +dnspython==2.7.0 +Flask==3.1.0 +Flask-Bcrypt==1.0.1 +gunicorn==23.0.0 +idna==3.10 +itsdangerous==2.2.0 +Jinja2==3.1.6 +MarkupSafe==3.0.2 +packaging==24.2 +pymongo==4.11.3 +requests==2.32.3 +soupsieve==2.6 +typing_extensions==4.13.0 +urllib3==2.3.0 +Werkzeug==3.1.3 diff --git a/scripts/database/mongo.py b/scripts/database/mongo.py index cc4dffa..3e97b0b 100644 --- a/scripts/database/mongo.py +++ b/scripts/database/mongo.py @@ -1,5 +1,9 @@ -from pymongo import MongoClient +from pymongo.mongo_client import MongoClient +from pymongo.server_api import ServerApi +import Constants +import certifi -# Monogo -mongo_client = MongoClient("mongodb://localhost:27017/") -mongo_database = mongo_client["recipedb"] +uri = Constants.MONGO_CONNECTION_STRING + +client = MongoClient(uri, server_api=ServerApi('1'), tlsCAFile=certifi.where()) +mongo_database = client["index-cooking"] \ No newline at end of file diff --git a/scripts/recipes/handle_recipes.py b/scripts/recipes/handle_recipes.py index 76faf86..22ba0a4 100644 --- a/scripts/recipes/handle_recipes.py +++ b/scripts/recipes/handle_recipes.py @@ -2,7 +2,7 @@ from bson.objectid import ObjectId from scripts.database.mongo import mongo_database from scripts.scraping.scraper import scrape -mongo_collection = mongo_database["recipes"] +mongo_collection = mongo_database.get_collection("recipes") def add_single_recipe(recipe): added_recipe = mongo_collection.insert_one(recipe) @@ -31,6 +31,13 @@ def delete_single_recipe(objectId): except: return {"success": False, "error": "Could not delete recipe"} +def delete_multiple_recipes(user): + try: + mongo_collection.delete_many({"user": user}) + return {"success": True} + except: + return {"success": False} + def search_recipes(query_data, user): query = query_data["q"] facets_list = [] diff --git a/scripts/scraping/scraper.py b/scripts/scraping/scraper.py index 50b46ae..8919d46 100644 --- a/scripts/scraping/scraper.py +++ b/scripts/scraping/scraper.py @@ -3,33 +3,59 @@ from urllib import parse import json from bs4 import BeautifulSoup +def extractInstructions(instructions): + returnedInstructions = [] + for inst in instructions: + + # If there are sub sections, parse them + if "itemListElement" in inst: + print("hitting sub") + subObj = {} + subInst = [] + subObj["name"] = inst["name"] + for el in inst["itemListElement"]: + subInst.append(el["text"]) + subObj["subInstructions"] = subInst + returnedInstructions.append(subObj) + + # Else we have a shallower array of instructions + else: + returnedInstructions.append(inst["text"]) + + return returnedInstructions + + def scrape(url, user_name): - data = requests.get(url, headers= {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}) - html = BeautifulSoup(data.text, 'html.parser') - inner_html = html.find('script', class_='yoast-schema-graph') - json_data = json.loads(inner_html.contents[0]) - graph_data = json_data["@graph"] - for i in graph_data: - if(i["@type"] == "Recipe"): - recipe = {} - instructions = [] - for instruction in i["recipeInstructions"]: - instructions.append(instruction["text"]) - keywords_list = i["keywords"].split(",") - tags = i["recipeCuisine"] + keywords_list - cleaned_tags = list(set([tag.strip().lower() for tag in tags])) - slug = parse.quote(i["name"]).lower() - - # The recipe - recipe["user"] = user_name - recipe["slug"] = slug - recipe["title"] = i["name"] - recipe["image"] = i["image"][0] - recipe["url"] = i["mainEntityOfPage"] - recipe["tags"] = cleaned_tags - recipe["ingredients"] = i["recipeIngredient"] - recipe["instructions"] = instructions - recipe["visible_by"] = ["jez"] - # recipe["encoded_url"] = urllib.parse.quote(i["name"]) - # Complete this all later!! - return recipe + try: + data = requests.get(url, headers= {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}) + html = BeautifulSoup(data.text, 'html.parser') + inner_html = html.find('script', class_='yoast-schema-graph') + json_data = json.loads(inner_html.contents[0]) + graph_data = json_data["@graph"] + # print(graph_data, "graph data") + for i in graph_data: + if(i["@type"] == "Recipe"): + recipe = {} + instructions = extractInstructions(i["recipeInstructions"]) + keywords_list = i["keywords"].split(",") + tags = i["recipeCuisine"] + keywords_list + cleaned_tags = list(set([tag.strip().lower() for tag in tags])) + slug = parse.quote(i["name"]).lower() + + # The recipe + recipe["user"] = user_name + recipe["slug"] = slug + recipe["title"] = i["name"] + recipe["image"] = i["image"][0] + recipe["url"] = i["mainEntityOfPage"] + recipe["tags"] = cleaned_tags + recipe["ingredients"] = i["recipeIngredient"] + recipe["instructions"] = instructions + recipe["visible_by"] = ["jez"] + # recipe["encoded_url"] = urllib.parse.quote(i["name"]) + + return {"success": True, "data": recipe} + + except Exception as e: + print(str(e)) + return {"success": False, "error": "couldn't scrape site metadata"} diff --git a/scripts/users/handle_users.py b/scripts/users/handle_users.py index 87ff7cd..250c716 100644 --- a/scripts/users/handle_users.py +++ b/scripts/users/handle_users.py @@ -1,5 +1,5 @@ from scripts.database.mongo import mongo_database -mongo_collection = mongo_database["users"] +mongo_collection = mongo_database.get_collection("users") def user_exists(user): try: @@ -11,16 +11,6 @@ def user_exists(user): except: return {"success": False, "error": "Request error, try again"} -def authenticate_user(user, password_matches): - try: - res = mongo_collection.find_one({"name": user}) - if res is None: - return {"success": False, "error": "Password doesn't match, try again"} - else: - return {"success": True, "user": user} - except: - return {"success": False, "error": "Something went wrong matching your password"} - def add_user(user, password): try: res = mongo_collection.insert_one({"name": user, "password": password}) @@ -28,3 +18,9 @@ def add_user(user, password): except: print("error") +def delete_single_user(user): + try: + mongo_collection.delete_one({"name": user}) + return {"success": True, "user": user} + except: + return {"success": False, "user": user} \ No newline at end of file diff --git a/server.py b/server.py index 013089a..7840ea3 100644 --- a/server.py +++ b/server.py @@ -1,17 +1,16 @@ from flask import Flask, Response, render_template, request, session, redirect, url_for +from flask_bcrypt import Bcrypt import functools import re -from scripts.database.mongo import mongo_database +import Constants from scripts.scraping.scraper import scrape -from scripts.recipes.handle_recipes import recipe_exists, add_single_recipe, get_all_recipes, get_single_recipe, get_facets, delete_single_recipe, search_recipes -from scripts.users.handle_users import user_exists, authenticate_user, add_user -from flask_bcrypt import Bcrypt +from scripts.recipes.handle_recipes import recipe_exists, add_single_recipe, get_all_recipes, get_single_recipe, get_facets, delete_single_recipe, search_recipes, delete_multiple_recipes +from scripts.users.handle_users import user_exists, add_user, delete_single_user -# Bcrypt.check_password_hash(hashed_password, "eligible password") app = Flask(__name__) bcrypt = Bcrypt(app) app.config["TEMPLATES_AUTO_RELOAD"] = True -app.secret_key = 'wdkbahjfbqb' +app.secret_key = Constants.SECRET_KEY # Decorator function to check for username in session to protect routes def login_required(func): @@ -26,6 +25,7 @@ def login_required(func): @app.route("/home") @login_required def home_page(): + print(session["username"]) tags = get_facets(session["username"]) all_recipes = get_all_recipes(session["username"]) return render_template("/pages/home.html",recipes=all_recipes, facets=tags) @@ -38,6 +38,13 @@ def landing_page(): @login_required def single_recipe_page(recipe_id): recipe_details = get_single_recipe(recipe_id) + + # If there are instruction sections, be sure to render correctly + if "subInstructions" in recipe_details["instructions"][0]: + new_instructions = [{"i": x["subInstructions"], "n": x["name"]} for x in recipe_details["instructions"]] + recipe_details["instructions"] = new_instructions + recipe_details["has_subsections"] = True + return render_template("/pages/single-recipe.html", single_recipe=recipe_details) @app.route("/login") @@ -65,18 +72,23 @@ def add_recipe(): req_data = request.form.to_dict() submitted_url = req_data["url"] if submitted_url == '': - return "No recipe supplied!" + return "No recipe supplied!", 422 does_recipe_exist = recipe_exists(session["username"], submitted_url) if does_recipe_exist: - return "

Recipe already exists

" + return "Recipe already exists!", 422 else: - recipe_json = scrape(submitted_url, session["username"]) - add_single_recipe(recipe_json) - all_recipes = get_all_recipes(session["username"]) - all_facets = get_facets(session["username"]) - return render_template("/components/app.html", recipes=all_recipes, facets=all_facets) + response = scrape(submitted_url, session["username"]) + + if response["success"]: + add_single_recipe(response["data"]) + all_recipes = get_all_recipes(session["username"]) + all_facets = get_facets(session["username"]) + return render_template("/components/app.html", recipes=all_recipes, facets=all_facets) + else: + return f"Error processing recipe metadata, {response['error']} ", 422 + @app.post("/recipes/search") def search(): @@ -115,12 +127,16 @@ def login_user(): @app.post("/signup") def signup_user(): req_data = request.form.to_dict() - user = req_data["username"] - pw = req_data["password"] + user = req_data.get("username") + pw = req_data.get("password") + pw_confirm = req_data.get("password-confirm") if user == "" or pw == "": return "

You must fill in both username and password

" + if pw != pw_confirm: + return "

Passwords do not match

" + res = user_exists(user) if res["success"] and res["user"] is not None: return "

User already exists, Login instead

" @@ -141,4 +157,17 @@ def signup_user(): @app.post("/logout") def logout_user(): session.pop('username', None) - return Response(headers={"HX-Redirect": "/"}) \ No newline at end of file + return Response(headers={"HX-Redirect": "/"}) + +@app.delete("/delete-account") +def delete_user(): + delete_user_res = delete_single_user(session["username"]) + delete_recipes_res = delete_multiple_recipes(session["username"]) + if delete_user_res["success"] and delete_recipes_res["success"]: + session.pop("username", None) + return Response(headers={"HX-Redirect": "/"}) + else: + return "Something went wrong deleting the user and recipes" + +if __name__ == "__main__": + app.run(host="0.0.0.0") diff --git a/static/images/bars.svg b/static/images/bars.svg new file mode 100644 index 0000000..64dd5a8 --- /dev/null +++ b/static/images/bars.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/scripts/htmx-targets.js b/static/scripts/htmx-targets.js new file mode 100644 index 0000000..26fffc3 --- /dev/null +++ b/static/scripts/htmx-targets.js @@ -0,0 +1,129 @@ +(function() { + /** @type {import("../htmx").HtmxInternalApi} */ + var api + + var attrPrefix = 'hx-target-' + + // IE11 doesn't support string.startsWith + function startsWith(str, prefix) { + return str.substring(0, prefix.length) === prefix + } + + /** + * @param {HTMLElement} elt + * @param {number} respCode + * @returns {HTMLElement | null} + */ + function getRespCodeTarget(elt, respCodeNumber) { + if (!elt || !respCodeNumber) return null + + var respCode = respCodeNumber.toString() + + // '*' is the original syntax, as the obvious character for a wildcard. + // The 'x' alternative was added for maximum compatibility with HTML + // templating engines, due to ambiguity around which characters are + // supported in HTML attributes. + // + // Start with the most specific possible attribute and generalize from + // there. + var attrPossibilities = [ + respCode, + + respCode.substring(0, 2) + '*', + respCode.substring(0, 2) + 'x', + + respCode.substring(0, 1) + '*', + respCode.substring(0, 1) + 'x', + respCode.substring(0, 1) + '**', + respCode.substring(0, 1) + 'xx', + + '*', + 'x', + '***', + 'xxx' + ] + if (startsWith(respCode, '4') || startsWith(respCode, '5')) { + attrPossibilities.push('error') + } + + for (var i = 0; i < attrPossibilities.length; i++) { + var attr = attrPrefix + attrPossibilities[i] + var attrValue = api.getClosestAttributeValue(elt, attr) + if (attrValue) { + if (attrValue === 'this') { + return api.findThisElement(elt, attr) + } else { + return api.querySelectorExt(elt, attrValue) + } + } + } + + return null + } + + /** @param {Event} evt */ + function handleErrorFlag(evt) { + if (evt.detail.isError) { + if (htmx.config.responseTargetUnsetsError) { + evt.detail.isError = false + } + } else if (htmx.config.responseTargetSetsError) { + evt.detail.isError = true + } + } + + htmx.defineExtension('response-targets', { + + /** @param {import("../htmx").HtmxInternalApi} apiRef */ + init: function(apiRef) { + api = apiRef + + if (htmx.config.responseTargetUnsetsError === undefined) { + htmx.config.responseTargetUnsetsError = true + } + if (htmx.config.responseTargetSetsError === undefined) { + htmx.config.responseTargetSetsError = false + } + if (htmx.config.responseTargetPrefersExisting === undefined) { + htmx.config.responseTargetPrefersExisting = false + } + if (htmx.config.responseTargetPrefersRetargetHeader === undefined) { + htmx.config.responseTargetPrefersRetargetHeader = true + } + }, + + /** + * @param {string} name + * @param {Event} evt + */ + onEvent: function(name, evt) { + if (name === 'htmx:beforeSwap' && + evt.detail.xhr && + evt.detail.xhr.status !== 200) { + if (evt.detail.target) { + if (htmx.config.responseTargetPrefersExisting) { + evt.detail.shouldSwap = true + handleErrorFlag(evt) + return true + } + if (htmx.config.responseTargetPrefersRetargetHeader && + evt.detail.xhr.getAllResponseHeaders().match(/HX-Retarget:/i)) { + evt.detail.shouldSwap = true + handleErrorFlag(evt) + return true + } + } + if (!evt.detail.requestConfig) { + return true + } + var target = getRespCodeTarget(evt.detail.requestConfig.elt, evt.detail.xhr.status) + if (target) { + handleErrorFlag(evt) + evt.detail.shouldSwap = true + evt.detail.target = target + } + return true + } + } + }) +})() diff --git a/static/scripts/index.js b/static/scripts/index.js new file mode 100644 index 0000000..65c3c12 --- /dev/null +++ b/static/scripts/index.js @@ -0,0 +1,11 @@ +const modal = document.querySelector("dialog"); +const showModalBtn = document.querySelector("#show-modal"); +const closeModalBtn = document.querySelector("#close-modal"); + +showModalBtn.addEventListener("click", () => { + modal.showModal(); +}); + +closeModalBtn.addEventListener("click", () => { + modal.close(); +}); diff --git a/static/style/style.css b/static/style/style.css index 36a4373..748e8dd 100644 --- a/static/style/style.css +++ b/static/style/style.css @@ -1,11 +1,21 @@ :root { - --bg-colour: #1d1f27; - --font-colour: #c9d1d9; - --accent-colour: #8cc2dd; + --bg-colour: #fff; + --font-colour: #1d1f27; + --accent-colour: #3273dc; + --border-color: #ccc; --success: #4bb543; --error: #ff3333; } +/* Helpers */ +.error { + color: var(--error); +} + +.success { + color: var(--success); +} + body, html { min-height: 100%; @@ -14,7 +24,7 @@ html { body { background-color: var(--bg-colour); color: var(--font-colour); - font-family: "Verdana"; + font-family: "DM Sans", sans-serif; max-width: 900px; margin: 0 auto; padding: 15px; @@ -70,7 +80,7 @@ button { } hr { - border: 1px dashed #fff; + border: 1px dashed var(--border-color); margin: 20px 0; } @@ -118,10 +128,3 @@ figure figcaption { font-weight: 400; } -.error { - color: var(--error); -} - -.success { - color: var(--success); -} diff --git a/templates/base.html b/templates/base.html index 64ae319..3181a2f 100644 --- a/templates/base.html +++ b/templates/base.html @@ -5,9 +5,16 @@ index.cooking - {% block title %}{% endblock %} + + {% block scripts %} {% endblock %} + + - + {% include "/components/header.html" %}

{% block heading %}Some heading!{% endblock %}

{% block content %}{% endblock %} diff --git a/templates/components/app.html b/templates/components/app.html index 6a4c83a..f2fe587 100644 --- a/templates/components/app.html +++ b/templates/components/app.html @@ -1,7 +1,10 @@
-

Filter by tag

+
+

Filter by tag

+ loading indicator +
{% for facet in facets %} diff --git a/templates/pages/account.html b/templates/pages/account.html index db28632..10a3789 100644 --- a/templates/pages/account.html +++ b/templates/pages/account.html @@ -1,5 +1,11 @@ -{% extends "base.html" %} {% block title %} account {% endblock %} {% block -heading %} +{% extends "base.html" %} {% block scripts %} + + + +{% endblock %} {% block title %} account {% endblock %} {% block heading %}

Hey {{ session.username }} 👋

{% endblock %} {% block content %}

@@ -13,4 +19,13 @@ heading %} here.

+ + +

+ Are you sure you want to delete your account? This will erase all your data + including your recipes. +

+ + +
{% endblock %} diff --git a/templates/pages/home.html b/templates/pages/home.html index 6a5d4cd..c44a017 100644 --- a/templates/pages/home.html +++ b/templates/pages/home.html @@ -6,21 +6,33 @@ hx-trigger="submit load" hx-target=".app" hx-swap="innerHTML" + hx-indicator="#spinner" + hx-target-422="#form-error" + hx-target-5*="#form-error" > - +
+ + loading indicator +
+

search for recipes 🔎

- +
+ + loading indicator +
{% include "/components/app.html" %} {% endblock %} diff --git a/templates/pages/signup.html b/templates/pages/signup.html index c706074..99d6021 100644 --- a/templates/pages/signup.html +++ b/templates/pages/signup.html @@ -7,6 +7,8 @@ + +

diff --git a/templates/pages/single-recipe.html b/templates/pages/single-recipe.html index 35c03c0..d8c334d 100644 --- a/templates/pages/single-recipe.html +++ b/templates/pages/single-recipe.html @@ -12,11 +12,23 @@ endblock %} {% block content %} {% endfor %}

Instructions

+ {% if single_recipe.has_subsections %} + {% for instruction in single_recipe.instructions %} +

{{ instruction.n }}

+ + {% endfor %} + {% else %} + {% endif %} + - -
  • - - Reddit
  • - - -
    -

    About Alissa Saenz

    Hi, I'm Alissa! I'm a former attorney turned professional food blogger. I love creating vegan recipes with bold flavors! You can read more about me here.

    -

    I'd love to connect with you on Facebook, Instagram, or Pinterest.

    -

    Subscribe

    -

    Subscribe for email updates and receive a free copy of my veggie burger e-book!

    -
    - - -
    -
    -

    Reader Interactions

    Comments

      -
      -
      - 4.95 from 70 votes (31 ratings without comment) -
      -
      -
      -

      Leave a Reply

      Your email address will not be published. Required fields are marked *

      - -
      - Recipe Rating -




      -
      -
      -

      - -

      - -

      - -
    1. -
      - - -
      -

      - Sarah Mitchell says

      - -

      - -
      - -

      5 stars
      -This recipe is that golden combination of both very simple to make and very yummy to eat! It's really easy to get the sauce made, veggies steamed, and rice cooked while the tofu is baking so you never feel rushed and the cooking experience is relaxing and enjoyable. We like to serve it with broccoli and thinly sliced carrot rounds and dump the veggies in the sauce right along with the tofu. I can't speak to how it holds up as leftovers because we never have any! Lol. Definitely a new staple recipe in our household :)

      -
      - - - -
      -
    2. - -
    3. -
      - - -
      -

      - Heather says

      - -

      - -
      - -

      5 stars
      -The best teriyaki sauce! I omitted the sherry as suggested. Delicious!

      -
      - - - -
      -
    4. - -
    5. -
      - - -
      -

      - Søren says

      - -

      - -
      - -

      5 stars
      -This was delicious. My family loved this style of tofu as part of a rice bowl with various other toppings. I also made a spicier sichuan sauce on the size, which paired well.

      -
      - - - -
      -
    6. - -
    7. -
      - - -
      -

      - jennifer says

      - -

      - -
      - -

      This looks wonderful!
      -Do you think an air fryer could be used here, rather than baking the tofu? And at what temp and cook time?
      -And thank you for the delightful sauce recipe!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        Thank you! And it can absolutely be air fried!. 425°F for 15 minutes should be perfect. Enjoy!!

        -
        - - - -
        -
      • -
      -
    8. - -
    9. -
      - - -
      -

      - Kallie says

      - -

      - -
      - -

      5 stars
      -I've been making this recipe since the start of the pandemic and it has become an easy weeknight staple. The flavors are all there and once you invest in the key ingredients it becomes so easy to make this dish all the time for only the price of tofu and some scallions which was much appreciated when the world was shut down. Thank you so much for this recipe!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Carrie says

        - -

        - -
        - -

        5 stars
        -Delicious! Found this recipe tonight as hubby & I were mulling over what to cook. We had all of the ingredients & am glad we did! Only swaps were using less oil (we try to eat oil free but I didn’t know if leaving the oil put would ruin the baked tofu). I also used subbed coconut aminos for soy sauce. Served with broccoli (mixed the broccoli & tofu with the sauce) over brown rice. My family enjoyed it. Even my picky kiddo liked it enough that he ate all his tofu and broccoli. Only food he left over was rice. To me that is a win! Thanks for the great recipe. If you have suggestions on how to make it oil free, I am all ears. Will definitely be making this again!

        -
        - - - -
        -
          - -
        • -
          - - -
          -

          - Alissa Saenz says

          - -

          - -
          - -

          I'm glad you enjoyed it! The easiest way to make this oil free would be to skip the cornstarch coating and simply brown the tofu cubes in a nonstick skillet. Alternatively, if you really want a crispy coating you could try something like this: https://www.connoisseurusveg.com/tofu-nuggets/ without the oil mist. I'd make a little extra sauce if you go this route, because the coating ends up being so thick that your tofu pieces will have more surface area to cover!

          -
          - - - -
          -
        • -
        -
      • -
      -
    10. - -
    11. -
      - - -
      -

      - Emma says

      - -

      - -
      - -

      5 stars
      -So good! I made this recipe exactly as written and served over white rice and broccoli as pictured, and it was perfect. I also added a bit of chili crisp to each serving at the end for a little bit of spice. This is going into my regular meal rotation for sure!

      -
      - - - -
      -
    12. - -
    13. -
      - - -
      -

      - Maddie McCoy says

      - -

      - -
      - -

      5 stars
      -I served it with 1.5 cups (dry) brown rice, and microwave-steamed frozen broccoli! It says 4 servings but it was so good that my boyfriend and I ate all of it just the two of us for dinner! :)

      -
      - - - -
      -
    14. - -
    15. -
      - - -
      -

      - Joe Thompson says

      - -

      - -
      - -

      Is the simmering down of the sauce necessary? Could I just add less water?

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        You do need to at least simmer it briefly with the cornstarch in order to thicken it. Aside from that the simmering does build flavor, but it's not strictly necessary.

        -
        - - - -
        -
      • -
      -
    16. - -
    17. -
      - - -
      -

      - Sara says

      - -

      - -
      - -

      5 stars
      -The whole recipe is amazing, but the stand out is the way the tofu bakes. I have been vegan for almost 2 decades, absolutely adore tofu and I am a great cook, but this was the first time I had baked tofu come out perfectly (this recipe combines the right amount of coating/right temperature/time in oven #trifecta). It was insanely crispy, the texture was spot on and it held the sauce perfectly. This is going to be the recipe I send tofu hating friends and family, because not only is it easy and delicious but it shows how amazing tofu can be.

      -
      - - - -
      -
    18. - -
    19. -
      - - -
      -

      - Mark says

      - -

      - -
      - -

      5 stars
      -I made this with white rice and mixed steamed veggies (carrots, green pepper, baby bok choy). It was very delicious. There's a lot going on at once, but it all came together in a very tasty meal. I will definitely be making this again. I may even use the sauce with other things.

      -
      - - - -
      -
    20. - -
    21. -
      - - -
      -

      - Patricia says

      - -

      - -
      - -

      4 stars
      -Thank you for this wonderful recipe and for introducing me to baked tofu. My only concern was how salty the sauce was, even though I used low sodium Tamari. I will be trying some of the ideas mentioned to make it a little less salty and hope they don't take away from the wonderful taste too much. Still, the dish was delicious.

      -
      - - - -
      -
    22. - -
    23. -
      - - -
      -

      - Ali says

      - -

      - -
      - -

      I’m half way through Veganuary and was getting bored, so bought some teriyaki tofu. Delicious with jasmine rice and broccoli, thank you

      -
      - - - -
      -
    24. - -
    25. -
      - - -
      -

      - Anna says

      - -

      - -
      - -

      4 stars
      -Delicious!

      -
      - - - -
      -
    26. - -
    27. -
      - - -
      -

      - Clare says

      - -

      - -
      - -

      5 stars
      -Hello. My girlfriend is Spanish and I’m a vegetarian, difficult mix, she’d never had Tofu before and absolutely loved this!!! Thank you so much! It’s so amazing she gave it a 10/10

      -
      - - - -
      -
    28. - -
    29. -
      - - -
      -

      - Lola Drewery says

      - -

      - -
      - -

      5 stars
      -sooo good. Made it with a miso Kale salad and Yam and avocado sushi roll. Will make again!

      -
      - - - -
      -
    30. - -
    31. -
      - - -
      -

      - Cel says

      - -

      - -
      - -

      5 stars
      -YUM!! Teriyaki Tofu has always been my true love, but I had never attempted it until tonight. This recipe is amazing!

      -

      The most perfect lil tofus, I love the crispy outside. I tossed with sunflower oil and it worked great.
      -I paired it with some quinoa and pan roasted teriyaki zucchinis!

      -

      Thank you for this amazing recipe, it's my new go-to!

      -
      - - - -
      -
    32. - -
    33. -
      - - -
      -

      - Meeta says

      - -

      - -
      - -

      5 stars
      -never cooking tofu any other way again! this recipe was wonderful. even my 4 and 5 year old kids couldn't get enough tofu and sauce! thanks so much!

      -
      - - - -
      -
    34. - -
    35. -
      - - -
      -

      - Katy says

      - -

      - -
      - -

      5 stars
      -This is my first review ever for an recipe, but it was sooo delicious and easy to make that I must write one.
      -My husband and I are vegan and I've tried many recipes over the last months. We both love the asian kitchen and so I've found your recipe two days ago. I've made it yesterday and today again because this is one of the best recipes ever. I love the baked tofu and will definitely bake it from now on. Thank you so much for this fantastic recipe!

      -
      - - - -
      -
    36. - -
    37. -
      - - -
      -

      - Melissa says

      - -

      - -
      - -

      5 stars
      -It was perfect even though I didn’t have dry sherry or mirin. I also had to sub cornstarch for potato starch. Still delicious and perfect consistency and flavor.

      -
      - - - -
      -
    38. - -
    39. -
      - - -
      -

      - Alyssa says

      - -

      - -
      - -

      5 stars
      -I love this recipe! I've made it twice, once I fried the tofu instead of baking, it was delicious but even better when I had extra time to put it in the oven. I use it in sushi bowls with cucumber, avocado, seaweed, imitation crab and sircacha mayo.

      -
      - - - -
      -
    40. - -
    41. -
      - - -
      -

      - Michelle Neff-McCormack says

      - -

      - -
      - -

      5 stars
      -I make this on the regular. Usually for our weekday lunches. Such a great flavor and super easy to make!

      -
      - - - -
      -
    42. - -
    43. -
      - - -
      -

      - Sue Gordon says

      - -

      - -
      - -

      With the covid virus,I’ve not been able to get any dry sherry to make this recipe. I have all the other ingredients. What would you advise as a substitute? Thanks for any help you can provide. I’m hungry!!!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        You could try using dry white wine if that's available. If not, I'd just skip it! It adds flavor, but the sauce should still be delicious without it!

        -
        - - - -
        -
      • -
      -
    44. - -
    45. -
      - - -
      -

      - Seema Kumar says

      - -

      - -
      - -

      5 stars
      -We are a vegan family , My son is a very picky eater and likes variety in his food , that is why experimenting with other cuisines . It was super easy and absolutely delicious. Tofu was very well done and the end product was better than restaurant style , Will try other recipes as well from your site .

      -

      Thanks again for making my day !

      -
      - - - -
      -
    46. - -
    47. -
      - - -
      -

      - jancrs says

      - -

      - -
      - -

      5 stars
      -Excellent recipe— thanks! I fried the tofu in sesame oil and added lots of stir fried vegetables (onion, sweet peppers, and snow peas in addition to the broccoli). It was a big hit! I am excited to try your other recipes.

      -
      - - - -
      -
    48. - -
    49. -
      - - -
      -

      - Kristine Bacharach says

      - -

      - -
      - -

      5 stars
      -I made this for my family last night after stumbling onto your site. My New Year’s resolution this year was to incorporate at least one vegetarian meal per week. This was a hit! My husband and mother-in-law both said it was really good, and both were reluctant when I told them we were having tofu for dinner. The texture was good and the sauce was amazing! I served it with jasmine rice and snow peas. Thank you for a great recipe that was quick and easy to prepare

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Kellyn says

        - -

        - -
        - -

        3 stars
        -I used half the soy sauce and replaced the rest with water and it was still profoundly salty, but the end result was a beautiful looking teriyaki sauce. The flavor would have been better if it was so ridiculously salty. I plan to make this again with 2 tbsp soy sauce and ¾ cup water and not toss the tofu in soy sauce.

        -
        - - - -
        -
      • -
      -
    50. - -
    51. -
      - - -
      -

      - Alison Forness says

      - -

      - -
      - -

      The recipe sounds delicious! My only concern is the use of canola oil, probably the worst oil there is for human consumption. As a holistic health coach I would never recommend it. Avocado or grape seed are better alternatives

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Nikki says

        - -

        - -
        - -

        5 stars
        -Agreed

        -
        - - - -
        -
      • -
      -
    52. - -
    53. -
      - - -
      -

      - Catherine says

      - -

      - -
      - -

      4 stars
      -I will definitely be baking my tofu from now on. We all loved it. The sauce, however, was very salty (and I’m a salt fiend) but I possible simmered it for too long. I’ll add more sugar and water next time. Having said that, serving it with rice, broccoli and sugar snaps was perfect. Will be making this again.

      -
      - - - -
      -
    54. - -
    55. -
      - - -
      -

      - faith says

      - -

      - -
      - -

      5 stars
      -We LOVED this recipe! I've made it twice now. The second time I must've used too much cornstarch in the sauce and it was slimy... so watch out for that! Otherwise, this was easy, quick, cheap and DELICIOUS!!!

      -
      - - - -
      -
    56. - -
    57. -
      - - -
      -

      - Kate says

      - -

      - -
      - -

      5 stars
      -It's not that easy to find such repices in German language. Most of Japanese food isn't vegan in my country so I enjoyed this recipe so much. I am so in love with that sauce, I added more garlic and it's so perfect.
      -I am going to cook it more often.

      -

      Thank you so much!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        Yay! Very welcome! I'm so glad you like it!

        -
        - - - -
        -
      • -
      -
    58. - -
    59. -
      - - -
      -

      - Ramie says

      - -

      - -
      - -

      5 stars
      -Thank you so much for sharing this incredible recipe. I added some red pepper flakes and the meal was delicious. Thank you thank you!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        Sounds delicious! Glad you like it!

        -
        - - - -
        -
      • -
      -
    60. - -
    61. -
      - - -
      -

      - Jessica says

      - -

      - -
      - -

      5 stars
      -I just made this for a lazy sunday lunch/dinner. Super easy and delicious!!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        I'm so glad you like it!

        -
        - - - -
        -
      • -
      -
    62. - -
    63. -
      - - -
      -

      - Paige says

      - -

      - -
      - -

      5 stars
      -I’m not kidding when I say I make this every week for meal prep. It’s about the only meal I can find to eat 5 days in a row. It is DELICIOUS. When I want it spicy I add a tablespoon of Korean-style red pepper. Also add in a few splashes of vegan fish sauce. Absolutely love this recipe. Definitely makes tofu delicious!!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        I'm so glad you like it! I'm intrigued by vegan fish sauce - do you buy it or make your own? Now I want to get my hands on some and try it out!

        -
        - - - -
        -
          - -
        • -
          - - -
          -

          - Alice says

          - -

          - -
          - -

          I'm not sure about vegan fish sauce. But kelp powder is usually used for vegan fish flavour in vegan dishes. That I know of anyway. A tiny amount goes a long way and so it lasts for ages. Adds a lot of depth of flavour and is great for anything ""fishy"" you want to make. Or just to add some flavour.

          -
          - - - -
          -
        • -
        -
      • -
      -
    64. - -
    65. -
      - - -
      -

      - Evey says

      - -

      - -
      - -

      5 stars
      -I decided on the spot to make this, so I didn’t have every single ingredient. I either improvised or left a couple of things out (and added mushrooms and skinny sliced red peppers) and it still turned out quite wonderful. Was proud of that homemade Teriyaki sauce! And the baked tofu is the way to go! Thanks for creating this delicious recipe!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        I'm glad it worked out and you enjoyed it! Thanks so much Evey!

        -
        - - - -
        -
      • -
      -
    66. - -
    67. -
      - - -
      -

      - Ari says

      - -

      - -
      - -

      5 stars
      -So yum!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        I'm glad you think so!

        -
        - - - -
        -
      • -
      -
    68. - -
    69. -
      - - -
      -

      - Thom Kolton says

      - -

      - -
      - -

      5 stars
      -I marinated the tofu in soy sauce before dipping it in the mixture and backing it. Mistake. The tofu browned up very nicely, but didn't get crispy. I think there was just too much moisture in the tofu. Still, it was a absolutely delicious and, while I thought I had increased the recipe too much, there were leftovers. I will make this again and again.

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        I'm so glad you enjoyed it! Thanks Thom!

        -
        - - - -
        -
      • -
      -
    70. - -
    71. -
      - - -
      -

      - Cindy says

      - -

      - -
      - -

      5 stars
      -This was the second time I have made this dish. My husband just loves it. Thanks for showing me how to make crispy tofu in the oven.

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        I'm so glad you like it! Thanks so much Cindy!

        -
        - - - -
        -
      • -
      -
    72. - -
    73. -
      - - -
      -

      - Jeff says

      - -

      - -
      - -

      5 stars
      -I made this tonight. It was very easy. I had never baked tofu before (I've always fried it) and got rave reviews from the family.

      -

      One of my daughters didn't like it, but everyone else loved it, including me.This will be in our dinner rotation.

      -

      It was a really great change from fried tofu.

      -

      Since you add the sauce last, you can have some tofu for pickier eaters and the sauce for everyone else.

      -

      The sesame seeds REALLY add to the flavor.

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        I'm so glad it was a hit! Thanks Jeff!!

        -
        - - - -
        -
      • - -
      • -
        - - -
        -

        - Nicholas Parkes says

        - -

        - -
        - -

        Should we / Did you use raw sesame seeds or did you toast them?

        -
        - - - -
        -
          - -
        • -
          - - -
          -

          - Alissa Saenz says

          - -

          - -
          - -

          I prefer toasted (I buy them that way) but raw sesame seeds can work to. Whichever you prefer!

          -
          - - - -
          -
        • -
        -
      • -
      -
    74. - -
    75. -
      - - -
      -

      - John says

      - -

      - -
      - -

      5 stars
      -It was my turn to cook dinner, and I found this recipe. We had most of the ingredients, so away I went. I fried the tofu in a frying pan instead of baking it in the oven. It was easier, and faster for me to do it that way. Otherwise, I followed the recipe word for word. We were very happy with the results! Now it's another option for the age old question, "What's for dinner?"

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        Yay! I'm so glad you enjoyed it! Thanks so much John!

        -
        - - - -
        -
          - -
        • -
          - - -
          -

          - dawn says

          - -

          - -
          - -

          4 stars
          -Hi! I’m an amateur cook so this was a bit challenging for me. I found that in the end result the sauce have this weird salty sourly taste and I was wondering what would you recommend to make it more sweeter and less powering.

          -
          - - - -
          -
            - -
          • -
            - - -
            -

            - Alissa Saenz says

            - -

            - -
            - -

            Hi Dawn! Try adding a bit of extra brown sugar to balance out the salty and tart flavors. Just add 1 tablespoon at a time when the sauce is just about done, until you're happy with the flavor.

            -
            - - - -
            -
          • -
          -
        • -
        -
      • -
      -
    76. - -
    77. -
      - - -
      -

      - vivian says

      - -

      - -
      - -

      5 stars
      -I really enjoyed this recipe, both the taste and how easy it was to make. Served with roasted broccoli and jasmine rice and veggie spring rolls. Thanks for a great recipe!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        Sounds like a delicious meal! Glad you enjoyed it!

        -
        - - - -
        -
          - -
        • -
          - - -
          -

          - Clare says

          - -

          - -
          - -

          5 stars
          -This is the best teriyaki sauce I've come across! Will hold onto this recipe. Thank you!

          -
          - - - -
          -
        • -
        -
      • -
      -
    78. - -
    79. -
      - - -
      -

      - Connie says

      - -

      - -
      - -

      5 stars
      -I made this the other night and it was really good. Thanks!

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alissa Saenz says

        - -

        - -
        - -

        I'm so glad you enjoyed it! Thanks Connie!

        -
        - - - -
        -
      • - -
      • -
        - - -
        -

        - Valarie Napawanetz says

        - -

        - -
        - -

        We made it tonight and I was astonished at how delicate and delicious this was. The tofu was perfect. I cut mine into thin slices and basted each slice with the teriyaki sauce. Then adds more according to the recipe when serving. I served with sautéed Bok choy. Excellent. Loved it. The sauce is amazing.

        -
        - - - -
        -
      • -
      -
    80. - -
    81. -
      - - -
      -

      - Barb says

      - -

      - -
      - -

      5 stars
      -As soon as I saw this recipe I knew it was dinner. I made the sauce ahead of time and reheated once the tofu came out. I cheated and used ginger paste and garlic powder in the same equivalent (because, Monday...) but I can only imagine it'd be that much better with the fresh versions. Served it over organic brown rice and steamed broccoli and it was excellent! I'm not even that big of a teriyaki fan but this is definitely a keeper. Thank you, your recipes never fail me.

      -
      - - - -
      -
        - -
      • -
        - - -
        -

        - Alexandra Kenin says

        - -

        - -
        - -

        5 stars
        -This teriyaki sauce was THE BOMB. Thank you!!

        -
        - - - -
        -
      • -
      -
    82. -
    -
    - - -
    - -
    - -
    - -
    -
    - - -
    - -
    - -
    -

    NEVER MISS A RECIPE

    -

    Subscribe and I'll send you my free VEGAN DINNER SOLUTIONS email series.

    -
    -
    -
    Vegetable Chow Mein -
    -
    - -
    -
    -
    -
    - -
    -
    -
    -
    -
    - -
    -
    -
    - -
    -
    - -
    -
    -
    -
    -
    - -
    -
    - -
    - - - - - -
    -
    -
    - -
    - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.2.3