Recipe Finder App with HTML, CSS & JavaScript
30 DAYS 30 PROJECT CHALLENGE
Day #27
Project Overview
A Recipe Finder App built using HTML, CSS, and JavaScript that allows users to search and discover recipes by name.
The application fetches real-time recipe data from a public food API and displays recipe details in a clean and user-friendly interface.
Key Features
- Search recipes by keyword or dish name.
- Fetches real-time recipe data using a public API.
- Displays recipe images, category, and origin.
- Provides direct links to full recipe instructions.
- Handles loading and no-result scenarios gracefully.
- Clean, responsive, and user-friendly design.
- No API key required.
HTML Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Recipe Finder App</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="recipe-container">
<h2>Recipe Finder</h2>
<div class="search-box">
<input
type="text"
id="searchInput"
placeholder="Search recipe (e.g. pasta, chicken)"
/>
<button onclick="getRecipes()">Search</button>
</div>
<div id="recipeList" class="recipe-list"></div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS Code
* {
box-sizing: border-box;
font-family: "Segoe UI", sans-serif;
}
body {
min-height: 100vh;
background: #042453;
display: flex;
justify-content: center;
align-items: flex-start;
padding-top: 40px;
}
.recipe-container {
background: #ffffff;
width: 450px;
padding: 25px;
border-radius: 14px;
box-shadow: 0 20px 40px rgba(0,0,0,0.25);
}
h2 {
text-align: center;
margin-bottom: 15px;
}
.search-box {
display: flex;
margin-bottom: 15px;
}
.search-box input {
flex: 1;
padding: 10px;
border-radius: 6px 0 0 6px;
border: 1px solid #ccc;
}
.search-box button {
padding: 10px 16px;
border: none;
border-radius: 0 6px 6px 0;
background: #4f46e5;
color: white;
cursor: pointer;
}
.recipe-list {
display: flex;
flex-direction: column;
gap: 14px;
}
.recipe-card {
border: 1px solid #e5e7eb;
border-radius: 10px;
overflow: hidden;
}
.recipe-card img {
width: 100%;
height: 200px;
object-fit: cover;
}
.recipe-card .content {
padding: 12px;
}
.recipe-card h4 {
margin-bottom: 6px;
}
.recipe-card p {
font-size: 13px;
color: #555;
}
.recipe-card a {
display: inline-block;
margin-top: 8px;
font-size: 13px;
color: #4f46e5;
text-decoration: none;
}
.error {
color: red;
text-align: center;
}
Javascript Code
const recipeList = document.getElementById("recipeList");
function getRecipes() {
const query =
document.getElementById("searchInput").value.trim() || "chicken";
recipeList.innerHTML = "Loading...";
fetch(`https://www.themealdb.com/api/json/v1/1/search.php?s=${encodeURIComponent(query)}`)
.then(res => res.json())
.then(data => {
if (!data.meals) {
recipeList.innerHTML = `<p class="error">No recipes found</p>`;
return;
}
recipeList.innerHTML = "";
data.meals.slice(0, 5).forEach(meal => {
recipeList.innerHTML += `
<div class="recipe-card">
<img src="${meal.strMealThumb}" alt="${meal.strMeal}">
<div class="content">
<h4>${meal.strMeal}</h4>
<p><strong>Category:</strong> ${meal.strCategory}</p>
<p><strong>Area:</strong> ${meal.strArea}</p>
<a href="${meal.strSource || meal.strYoutube}" target="_blank">
View Recipe
</a>
</div>
</div>
`;
});
})
.catch(() => {
recipeList.innerHTML = `<p class="error">Error loading recipes</p>`;
});
}
Related Projects
Day 25 : Stock Price UI (Mock / API)
Displays stock prices and daily changes using mock data with API-ready structure.
Concepts: UI state management, dynamic rendering, data simulation.
Day 29 : IP Address Tracker
Tracks and displays location details of an IP address using a public API.
Concepts: API integration, async data fetching, dynamic UI rendering.
Day 30 : Public Holiday Finder
Finds and displays public holidays by country and year using a public API.
Concepts: API integration, async data fetching, dynamic UI rendering.