Skip to content

Oohnohassani/Forkify

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A recipe search and bookmarking app that lets you browse 1M+ meals, adjust serving sizes, and save your favourites — built with vanilla JS and the Forkify API.

JavaScript HTML5 CSS3 Parcel License

⚠️ Desktop only — this app is not optimised for mobile or tablet viewports.

📸 Preview

forkify application screenshot

✨ Features

  • 🔍 Search 1,000,000+ recipes powered by the Forkify API
  • 📖 Detailed recipe view with ingredients, cooking time, and servings
  • ⚖️ Dynamic serving adjuster — ingredient quantities scale automatically
  • 🔖 Bookmark your favourites — persisted in localStorage; no account or backend needed
  • Upload your own recipes using the built-in form
  • 📄 Pagination for clean browsing through large result sets

🏗️ Architecture & Design Principles

Forkify is a frontend-only, no-backend application. All state is managed in memory and persisted exclusively through the browser's localStorage — there is no server, database, or authentication layer.

MVC Pattern

The codebase follows a strict Model–View–Controller separation:

Layer Responsibility
model.js Application state, all API calls, localStorage read/write
views/*.js DOM rendering only — zero business logic
controller.js Wires model and views together; owns all event handler logic

Publisher–Subscriber (Pub/Sub)

Views expose a addHandler(handler) method (the publisher). The controller passes its own functions as subscribers at startup. This keeps views completely decoupled from the controller — a view never imports or calls the controller directly.

OOP with ES6 Classes

Every view extends a shared View base class that provides:

  • render(data) — generates markup and inserts it into the DOM
  • update(data) — diffs the new markup against the current DOM and patches only changed nodes, avoiding full re-renders
  • renderSpinner() / renderError() / renderMessage() — shared UI states
// Example: extending the base View
class RecipeView extends View {
  _parentElement = document.querySelector('.recipe');

  _generateMarkup() {
    return `<div class="recipe__title">${this._data.title}</div> ...`;
  }
}

Functional Programming Tendencies

While the view layer uses classes, the model and helpers lean functional:

  • Pure functions with no side effects wherever possible
  • Array.prototype.map, filter, reduce, and flatMap preferred over imperative loops
  • async/await with a shared getJSON helper for all network requests
  • State mutations are isolated to a single state object in model.js, never scattered across the app

🚀 Getting Started

Prerequisites

  • Node.js v14 or higher
  • npm (comes with Node)

Installation

# 1. Clone the repository
git clone https://github.com/your-username/forkify.git
cd forkify

# 2. Install dependencies
npm install

# 3. Start the development server
npm start

The app will open at http://localhost:1234 with hot reloading enabled.

Build for Production

npm run build

Output is placed in the dist/ folder, ready to deploy.

🔑 API Key

This project uses the Forkify API v2.

Searching works without a key. To upload your own recipes, generate a free key:

  1. Visit forkify-api.herokuapp.com
  2. Click Generate API Key
  3. Open src/js/config.js and replace the placeholder:
export const KEY = 'your-api-key-here';

🗂️ Project Structure

forkify/
├── src/
│   ├── img/                  # Static images & icons
│   ├── sass/                 # SCSS styles
│   └── js/
│       ├── controller.js     # App entry point & pub/sub wiring
│       ├── model.js          # State, API calls, localStorage persistence
│       ├── config.js         # App-wide constants (API URL, key, timeouts)
│       ├── helpers.js        # Pure utility functions (getJSON, timeout, etc.)
│       └── views/
│           ├── View.js           # Base class (render, update, error states)
│           ├── recipeView.js     # Recipe detail rendering
│           ├── searchView.js     # Search input handling
│           ├── resultsView.js    # Search results list
│           ├── bookmarksView.js  # Bookmarks panel
│           ├── paginationView.js # Page controls
│           └── addRecipeView.js  # Upload recipe modal
├── index.html
├── package.json
└── README.md

🛠️ Tech Stack

Concern Choice
Language Vanilla JavaScript (ES6+)
Paradigm OOP (ES6 classes) + functional style
Markup HTML5
Styling CSS3 / SASS
Bundler Parcel v2
API Forkify API v2 (external, read-only for search)
Persistence localStorage (no backend, no database)
Architecture MVC + Publisher–Subscriber

📖 How It Works

  1. SearchsearchView publishes the query; controller calls model.loadSearchResults(), then re-renders resultsView and paginationView.
  2. Recipe Detail — Clicking a result updates the URL hash; controller calls model.loadRecipe() and passes data to recipeView.render().
  3. Servings+ / buttons fire an event; the controller updates model.state and calls recipeView.update() to patch only the changed quantity nodes.
  4. Bookmarks — Toggling a bookmark mutates model.state.bookmarks, persists to localStorage, and re-renders bookmarksView. Bookmarks are restored from localStorage on page load.
  5. Upload — The modal form POSTs to the Forkify API with your key; on success the new recipe is loaded and bookmarked automatically.

⚠️ Known Limitations

  • Desktop only — no responsive/mobile layout implemented
  • No backend — data is stored in localStorage; clearing browser storage removes all bookmarks
  • No user accounts — bookmarks are local to the browser and device
  • API dependency — recipe data is sourced entirely from the external Forkify API

🤝 Contributing

Contributions are welcome! Please open an issue first to discuss what you'd like to change.

# Fork → branch → commit → pull request
git checkout -b feature/your-feature-name

📄 License

This project is licensed under the MIT License.

🙏 Acknowledgements

  • Recipe data provided by the Forkify API
  • Project inspired by Jonas Schmedtmann's JavaScript course

About

A recipe search and bookmarking app that lets you browse 1M+ meals, adjust serving sizes, and save your favourites — built with vanilla JS and the Forkify API.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors