Skip to content

Conversation

@KausarShangareeva
Copy link

@KausarShangareeva KausarShangareeva commented Oct 10, 2025

Hi there! 👋
I built Recipe Library as part of my Technigo JavaScript Bootcamp 2025 journey. This project lets users explore and save dessert recipes from different cuisines in a fun and interactive way.

Check out the live website here: Recipe Library

Key Features:

  • Filter desserts by cuisine (Italy / Asia / Middle East)
  • Random dessert generator for fun inspiration
  • Favorites saved locally using LocalStorage
  • Handles API limits and caches data for offline use
  • Fully responsive design for mobile, tablet, and desktop

This project helped me practice working with APIs, dynamic content, local storage, and creating interactive, responsive UI components. 🌟

Copy link

@irisdgz irisdgz Oct 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think your HTML structure is nice and clean! It’s easy to see where each part of the app goes. Super nice you used main and section for the recipes whitch that makes it very readable. Maybe you could add an alt attribute (like a short description) to your images so it helps people using screen readers know what the picture shows :)

Copy link

@irisdgz irisdgz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice work Kausyar! The code is well structured and realtivly easy for me to follow. I like how you’ve added clear sections for rendering, filters and favorites. Cool to see how you’re using async/await and localStorage together. The filtering and sorting part is especially nice and works smoothly. Overall, super solid project eventhou it has its own style and not the one in the Figma demo!

const LS_COFFEE = "coffeeData";
const LS_JUICE = "juiceData";
const LS_FAVORITES = "favorites";

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of localStorage keys!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank!)

buttons.filter(Boolean).forEach((btn) => btn.classList.remove("active"));
if (activeBtn) activeBtn.classList.add("active");
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recognize this pattern from I dont remeber where, youtube or our session! Removing and adding classes to show active buttons. Nice and clean implementation!

if (coffeeRendered) return;
coffeeRendered = true;
if (containerCoffee) containerCoffee.innerHTML = "";

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of async/await to fetch the recipe data!


ensureNoMatchBanner(containerCoffee);
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice how you check localStorage first before fetching new data , here learned something myself as well :)

const isCoffee = category === "coffee";
const container = isCoffee ? containerCoffee : containerJuice;
if (!container) return;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well used async here again!

if (!cards || !cards.length) return null;
return cards[Math.floor(Math.random() * cards.length)];
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job here with random recpies.

item.parentElement
?.querySelectorAll(".filter__item")
.forEach((li) => li.classList.remove("active"));
item.classList.add("active");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! I like how you combine event listeners with sorting and filtering.

console.warn("No data-id on card");
return;
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool how you added a favorites feature! Great way to use localStorage and JSON to save user interactions

@JennieDalgren JennieDalgren self-assigned this Oct 23, 2025
Copy link

@JennieDalgren JennieDalgren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job with this project!

Take a look at the API calls and make sure yoou have data to be able to try your filters. I get empty states on almost all of them.

Really good implementation of favorite recipes and that is persists in local storage.

You project is not entirely responsive, see the screenshot:
image

Clean up your code a bit and work on the naming of your functions. If you change your "theme" of the recipes, change the names in your code too. Also, stick to english comments. And remember to use commit messages in a better way, the message should reflect the change that you have done in the code, do not just copy paste the same message every time, that really beats the purpose of commits.

What you need to fix:

  • Responsiveness
  • Make sure the filters you have chosen to work with is actually working
  • Clean up the code. Remove unused code, proper naming of variables and functions, english in comments if you need them.

Almost there! 💪

Comment on lines 5 to 29
:root {
--color-primary-first-light: #fafbff;
--color-primary-first: #0018a4;
--color-primary-second-light: #ffecea;
--color-primary-second: #ff6589;
--color-white: #ffffff;
--color-white-base: #ffffff;
--color-grey-light-1: #f8f9fa;
--color-grey-light-2: #e9ecef;
--color-grey-light-3: #dee2e6;
--color-grey-light-4: #ced4da;
--color-grey-dark: #868e96;
--color-grey-dark-base: #868e96;
--color-font: #212529;
--color-font-base: #212529;
--color-button: #8d9271;
--color-black: #000000;
--color-blue: #176d8c;
--border-radius-xxs: 0.5rem;
--border-radius-xs: 1rem;
--border-radius-sm: 1.5rem;
--border-radius-md: 2rem;
--border-radius-lg: 2.5rem;
--border-radius-xl: 3rem;
--box-shadow: 0 0.5rem 1rem #0019a453;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice that you use variables

css/style.css Outdated
------------------------------------ */
/*

ПЕРЕКЛЮЧЕНИЯ МЕЖДУ КАРТОЧКАМИ

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stick to english comments

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im done ✅✅✅

css/style.css Outdated
Comment on lines 772 to 773
border: 1px solid #e9ecef;
background-color: #e9ecef;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the variable that you have for this color?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im done ✅✅✅

css/style.css Outdated
}
.header__input-mobile:focus {
outline: none;
border-color: #e9ecef;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

variable?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im done ✅✅✅

Comment on lines 13 to 16
const mainCoffee = document.querySelector(".main-coffee");
const mainJuice = document.querySelector(".main-juice");
const mainTea = document.querySelector(".main-tea");
const mainFavorites = document.querySelector(".main-favorites");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very confused about all these drink references? That is not reflected in your deployed website, which looks like it is focused on desserts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im done ✅✅✅ I wrote desserts instead of juice

js/script.js Outdated
Comment on lines 129 to 139
if (
/(baklava|kunafa|kanafeh|maamoul|halva|tahini|rose\s*water|orange\s*blossom|middle\s*east|arab|leban|turk|persian|iran)/.test(
t
)
)
return "middle eastern";

const ing = ingredients.map((i) => String(i || "").toLowerCase()).join(" ");
if (/(mascarpone|savoiardi|amaretto)/.test(ing)) return "italian";
if (/(matcha|azuki|black\s*sesame|rice\s*flour)/.test(ing)) return "asian";
if (/(tahini|date|rose\s*water|orange\s*blossom|cardamom)/.test(ing))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very hard coded, why don't you use the cuisine data from the API instead?

Copy link
Author

@KausarShangareeva KausarShangareeva Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I simplified the cuisine detection function (detectCuisine). Now it only uses the cuisines field from the api data, and if the cuisine is not specified, it returns 'international'

Comment on lines +166 to +169
function toNum(v) {
const n = Number(v);
return Number.isFinite(n) ? n : 0;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you need this for?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toNum function is used for safely converting values to numbers when sorting the cards 😀

Comment on lines 253 to 255
seedIfEmpty(LS_COFFEE, DEMO_CAKES);
seedIfEmpty(LS_JUICE, DEMO_DESSERTS);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this actually be happening? You are supposed to fetch from the API?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're totally right to ask! Here’s the idea behind seedIfEmpty:

1- Fallback for API limits:
The Spoonacular API has strict limits (150 requests/day on the free plan). When the limit is reached, it returns a 402/429 error. Demo data makes sure the filters always work so you can test them.

2- Immediate UI feedback:
Without demo data, the user would see a blank screen while waiting for the API. With demo data, the interface shows content right away and updates it if the API responds.

js/script.js Outdated
Comment on lines 275 to 289
buttonCoffee?.addEventListener("click", () => {
mainCoffee?.classList.remove("hidden");
mainJuice?.classList.add("hidden");
mainTea?.classList.add("hidden");
mainFavorites?.classList.add("hidden");
setActiveButton(buttonCoffee);
});

//Turn on JUICE container and turn off the others
buttonJuice?.addEventListener("click", () => {
mainCoffee?.classList.add("hidden");
mainJuice?.classList.remove("hidden");
mainTea?.classList.add("hidden");
mainFavorites?.classList.add("hidden");
setActiveButton(buttonJuice);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the logic here, and it is nice. However I don't see any use of a coffee or juice button? Use names that makes sense for your project.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done ✅

Updated project description and added features, demo, technologies, and file structure.
Removed line breaks for a more concise introduction.
@KausarShangareeva
Copy link
Author

Good job with this project!

Take a look at the API calls and make sure yoou have data to be able to try your filters. I get empty states on almost all of them.

Really good implementation of favorite recipes and that is persists in local storage.

You project is not entirely responsive, see the screenshot: image

Clean up your code a bit and work on the naming of your functions. If you change your "theme" of the recipes, change the names in your code too. Also, stick to english comments. And remember to use commit messages in a better way, the message should reflect the change that you have done in the code, do not just copy paste the same message every time, that really beats the purpose of commits.

What you need to fix:

  • Responsiveness
  • Make sure the filters you have chosen to work with is actually working
  • Clean up the code. Remove unused code, proper naming of variables and functions, english in comments if you need them.

Almost there! 💪

Im done ✅✅✅

Copy link

@JennieDalgren JennieDalgren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KausarShangareeva KausarShangareeva changed the title Project Recipe Library – Kausyar Dessert Recipes Project – Technigo Bootcamp Project 2025 Dec 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants