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>`;
    });
}
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

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.