This project is a web app that helps people find recipe ideas based on what they feel like eating. Instead of making the user guess an exact dish name, the app starts with simple preferences like cravings, diet, meal type, country, or dinner. From there, it searches for recipes, gathers the useful details, and presents them in a clean and easy-to-read format.
In plain language, I built a tool that turns a vague thought like “I want something spicy for dinner” into actual meal ideas with ingredients, steps, and links to the full recipe.
People usually do not begin a food search by typing the exact name of a dish. Most of the time, they start with a feeling or preference. They may say, “I want something salty,” “I want food from Ghana,” or “I need a vegetarian breakfast.” That is the real-life behavior I designed this project around.
The goal of this app was to make that process easier. I wanted the user to be able to describe what they want in a natural way, and then let the application do the work of finding possible recipes, pulling out the important parts, and showing the best options first.
So rather than acting like a simple search bar, this project works more like a helper. It takes broad preferences, translates them into smarter searches, and then narrows down the results into something useful.
On many recipe websites, the user needs to already know what they are looking for. That means the search works best if someone types a very specific dish name, such as “jollof rice” or “banana bread.”
But that is not always how people think. Many people know the kind of food they want, but not the exact name of the meal.
I wanted to build an app that understands broader food intentions. A person should be able to say they want something spicy, a certain cuisine, a certain meal type, or a certain diet, and still get good results.
That is what makes the project more useful for everyday people. It starts from how people actually make food choices.
On the front of the app, the user sees a simple form with dropdown options. They can choose what they are craving, the cuisine or country they want to explore, their diet, and the type of meal.
After choosing those options, the user clicks a button and receives a list of recipe cards with images, ingredients, directions, and source links.
What the user sees is only the surface. In the background, the app is doing a lot more work. It takes the user's choices, builds a better search phrase, looks for recipe pages, reads the useful parts of those pages, compares them to the user’s preferences, and returns the strongest matches.
That is what makes this project more than just a pretty interface. It has a real decision-making process behind it.
These handle what the user sees and clicks. HTML gives the page structure, CSS gives it styling, and JavaScript makes it interactive so the form, buttons, and recipe results update without feeling static.
Flask is the part that receives the user’s request and does the main processing work. It acts like the brain of the app. When someone clicks “Get Recommendation,” Flask is what receives the request, starts the search process, and sends the final recipe data back.
SerpApi helps the app find recipe pages through search results. BeautifulSoup helps the app read the content on those pages. Once the app finds possible recipes, it needs a way to pull out the useful details like the title, image, ingredients, and cooking steps.
This is the easiest way to understand the project: follow one user action from start to finish.
Before writing code, I thought about what a normal person would actually want from a food app. Most people do not open a recipe site saying, “I want dish X.” They often say, “I want something sweet,” or “I want dinner from a certain country.” That idea shaped the entire project.
Because of that, I decided the app should begin with broad, human-friendly options instead of forcing exact recipe names.
I built a form with dropdown menus for craving, cuisine or country, diet, and meal type. I chose dropdowns because they make the experience simple and reduce typing mistakes.
This part matters because the quality of the output depends on the quality of the inputs. If the form is confusing, the whole experience feels harder. So I kept the input side clean and guided.
I included a Get Recommendation button, a Surprise Me button, and a Stop button. The Surprise Me feature makes the app more fun and exploratory, while the Stop button gives the user more control.
I also added pagination so the results would not all pile up in one long overwhelming page. This helped the app feel more polished and easier to use.
Once the user picks their options, JavaScript gathers those choices and sends them to Flask. This is the handoff point between the part the user sees and the part that does the deeper work.
You can think of this like placing an order at a restaurant: the customer gives the order to the server, and then the kitchen takes over. In this project, JavaScript passes the request, and Flask acts like the kitchen.
One of the most important parts of the project was not just taking the user's words literally. I created logic that combines the selected craving, cuisine, diet, and meal type into a more useful search phrase.
For example, if a user chooses India, the app may search using “Indian” because that wording is often more common on recipe websites. This improved the quality of the results.
After creating the search phrase, the app uses SerpApi to look up related pages. I treated these results as possible candidates, not as final answers.
That distinction is important. Just because a page appears in search results does not mean it is a perfect match. Some pages are list pages, some are low quality, and some do not fully match the user's request.
Once the app had possible links, I used BeautifulSoup and structured metadata parsing to read those pages and extract the most useful information. I focused on pieces like the recipe title, image, ingredient list, instructions, and source link.
This step is what transforms the project from “a list of links” into “actual recipe recommendations.” Instead of forcing the user to open many pages themselves, the app does some of that work first.
Web pages are not all written the same way. One recipe site might structure ingredients neatly, while another may scatter them differently. That means the raw data can be messy.
I added cleaning and formatting logic so the information would look more consistent before it was shown to the user. This included organizing ingredients and instruction steps into a readable format.
This is one of the most important parts of the project. I did not want the user to get whatever page happened to appear first. I wanted the app to decide which recipes were the strongest matches.
So I built ranking logic that checks how well each recipe matches the user's craving, cuisine, diet, and meal type. Recipes that match more of the user’s preferences are scored higher and shown first.
After the app finishes searching, cleaning, and ranking, it sends the final recipe data back to the frontend. JavaScript then displays each recommendation as a recipe card.
Each card gives the user the essentials at a glance: the recipe title, image, cuisine label, ingredients, instructions, and a link to the full source. That way, the user can quickly compare options without feeling overwhelmed.
If I had stopped at the search stage, this project would have felt like a basic wrapper around existing search results. That would not be very impressive or very useful. The real value comes from deciding which results deserve to be shown first.
For example, if someone asks for a spicy Nigerian dinner, not every recipe page that mentions Nigeria or spice should be treated the same. Some will be more relevant than others. My ranking logic helps sort those differences out.
In a non-technical sense, this is the part where the app starts to show judgment. It is trying to understand the user's intention, not just repeat whatever the internet throws back.
Building with live web data taught me that information is rarely handed to you in a neat format. A big part of development is cleaning and organizing data so it becomes useful.
The app could be technically functional but still not feel helpful if the recommendations are poor. This taught me that relevance and user satisfaction are part of the engineering work too.
Features like saved selections, a stop button, loading states, and pagination may seem small, but they make the app feel more polished and thoughtful.
If I continue developing this project, I would want to make it even more personalized and scalable.
This is the part of the app the user can actually see and interact with on the screen.
This is the behind-the-scenes part that processes requests, does the logic, and returns results.
An API is a way for one part of a system to talk to another. In this project, the page sends a request to the backend and receives recipe data back.
Scraping means reading web pages and pulling out useful information from them, such as recipe titles, ingredients, or instructions.
This is the method the app uses to decide which results are the best match and should be shown first.
This project helped me practice much more than just building a webpage. I had to think about the user’s real need, design a better search experience, work with outside data, clean messy information, and present the final results clearly.
What I like most about this project is that it shows how I approach problem-solving. I do not just want to make something look nice. I want to build tools that take a real everyday problem and make it simpler for the user.
In this case, the problem was food discovery. The solution was a recommendation app that starts with human preferences and turns them into useful meal ideas.