Table of Contents (click to expand)
Forkify app is a web app where users can search through more than 1 million recipes to find what they need. It shows all the necessary ingredients and how to make the dish. The users can bookmark their favourite recipes as well as add their own ones to the website. It has a beautiful and feature rich UI. The website is fully response in variety of screen sizes.
Live preview: Link
- HTML
- SASS (SCSS)
- TypeScript
- Forkify API
- AJAX
- Local storage API
- FormData API
- Webpack
- Babel
Requirements: node
and npm
If you do not have yarn
installed, install it using
npm install yarn -g # add sudo in mac and linux
Now
git clone https://github.com/DarshanVaishya/forkify-app
cd forkify-app
yarn install
yarn run build # To generate files
yarn run start # To start a local server
When performing data update, I realized that I was re-rendering the whole elements. This was bad for performance as well as having a flicker effect. To overcome this, I created a DOM update algorith, which only changes the elements which have their data changed.
// Had to use any as a lot of different data relied on this update
update(data: any) {
this.data = data;
const newMarkup = this.generateMarkup();
const newDOM = document.createRange().createContextualFragment(newMarkup);
const newEls = Array.from(newDOM.querySelectorAll("*"));
const curEls = Array.from(this.parentElement.querySelectorAll("*"));
for (let i = 0; i < curEls.length; i++) {
if (curEls[i].isEqualNode(newEls[i])) continue;
if (newEls[i].firstChild?.nodeValue.trim() !== "")
curEls[i].textContent = newEls[i].textContent;
Array.from(newEls[i].attributes).forEach((attr) => {
curEls[i].setAttribute(attr.name, attr.value);
});
}
}
Another challenge was to upload new recipes to the API. I learnt that fetch API can be used to upload data as well. I used the POST
method for uploading.
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(uploadData),
});
This project was a big undertaking for me, as I have never worked on a project of this scale. I learned a lot about the Model View Controller (MVC) Architecture. And for an added challenge, I made this project in Typescript.
My knowledge in Asynchronous JavaScript was strengthened. I realized and understood the need for TypeScript and how it helps in preventing bugs and unexpected behaviour.
.
├── babel.config.json
├── package.json
├── README.md
├── src
│ ├── img
│ │ ├── favicon.png
│ │ ├── icons.svg
│ │ ├── logo.png
│ │ ├── og-image.png
│ │ └── screenshots
│ │ ├── bookmarks.png
│ │ ├── main.png
│ │ ├── og-tag.png
│ │ ├── recipe.png
│ │ └── search.png
│ ├── sass
│ │ ├── _base.scss
│ │ ├── _components.scss
│ │ ├── _header.scss
│ │ ├── main.scss
│ │ ├── _preview.scss
│ │ ├── _recipe.scss
│ │ ├── _searchResults.scss
│ │ └── _upload.scss
│ ├── template.html
│ └── ts
│ ├── controller.ts
│ ├── model.ts
│ ├── util
│ │ ├── config.ts
│ │ ├── helpers.ts
│ │ └── interfaces.ts
│ └── views
│ ├── addRecipeView.ts
│ ├── bookmarksView.ts
│ ├── paginationVIew.ts
│ ├── previewView.ts
│ ├── recipeView.ts
│ ├── resultView.ts
│ ├── searchView.ts
│ └── view.ts
├── tsconfig.json
├── webpack.common.js
├── webpack.dev.js
├── webpack.prod.js
└── yarn.lock
7 directories, 39 files
If you have found a bug, suggesting an improvement or want to collaborate then please raise an issue or create an pull request.