diff --git a/growbros-frontend/.env b/growbros-frontend/.env
new file mode 100644
index 0000000000000000000000000000000000000000..53eb90ad013c59f02f208ddaf9cc8b89e38a2a75
--- /dev/null
+++ b/growbros-frontend/.env
@@ -0,0 +1 @@
+VITE_GROWBROS_BACKEND_URL = http://localhost:8080/api/v1
\ No newline at end of file
diff --git a/growbros-frontend/package-lock.json b/growbros-frontend/package-lock.json
index a1a72755876def8d514674d4c32587c117461d30..b9c0190f79675bd3a584482877d7163aa48e5e56 100644
--- a/growbros-frontend/package-lock.json
+++ b/growbros-frontend/package-lock.json
@@ -9,16 +9,15 @@
       "version": "0.0.0",
       "dependencies": {
         "font-awesome": "^4.7.0",
-        "jwt-decode": "^4.0.0",
+        "rc-slider": "^10.5.0",
         "react": "^18.2.0",
         "react-dom": "^18.2.0",
-        "react-modal": "^3.16.1",
-        "react-router-dom": "^6.18.0"
+        "react-router-dom": "^6.18.0",
+        "zod": "^3.22.4"
       },
       "devDependencies": {
         "@types/react": "^18.2.15",
         "@types/react-dom": "^18.2.7",
-        "@types/react-modal": "^3.16.3",
         "@typescript-eslint/eslint-plugin": "^6.0.0",
         "@typescript-eslint/parser": "^6.0.0",
         "@vitejs/plugin-react-swc": "^3.3.2",
@@ -38,6 +37,17 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/@babel/runtime": {
+      "version": "7.23.6",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz",
+      "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==",
+      "dependencies": {
+        "regenerator-runtime": "^0.14.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
     "node_modules/@esbuild/android-arm": {
       "version": "0.18.20",
       "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@@ -515,9 +525,9 @@
       }
     },
     "node_modules/@remix-run/router": {
-      "version": "1.13.1",
-      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.13.1.tgz",
-      "integrity": "sha512-so+DHzZKsoOcoXrILB4rqDkMDy7NLMErRdOxvzvOKb507YINKUP4Di+shbTZDhSE/pBZ+vr7XGIpcOO0VLSA+Q==",
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.11.0.tgz",
+      "integrity": "sha512-BHdhcWgeiudl91HvVa2wxqZjSHbheSgIiDvxrF1VjFzBzpTtuDPkOdOi3Iqvc08kXtFkLjhbS+ML9aM8mJS+wQ==",
       "engines": {
         "node": ">=14.0.0"
       }
@@ -738,17 +748,6 @@
       "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==",
       "dev": true
     },
-    "node_modules/@types/node": {
-      "version": "20.10.4",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz",
-      "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
-      "dependencies": {
-        "undici-types": "~5.26.4"
-      }
-    },
     "node_modules/@types/prop-types": {
       "version": "15.7.9",
       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz",
@@ -775,15 +774,6 @@
         "@types/react": "*"
       }
     },
-    "node_modules/@types/react-modal": {
-      "version": "3.16.3",
-      "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.3.tgz",
-      "integrity": "sha512-xXuGavyEGaFQDgBv4UVm8/ZsG+qxeQ7f77yNrW3n+1J6XAstUy5rYHeIHPh1KzsGc6IkCIdu6lQ2xWzu1jBTLg==",
-      "dev": true,
-      "dependencies": {
-        "@types/react": "*"
-      }
-    },
     "node_modules/@types/scheduler": {
       "version": "0.16.5",
       "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.5.tgz",
@@ -1132,6 +1122,11 @@
         "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
+    "node_modules/classnames": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
+      "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
+    },
     "node_modules/color-convert": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1435,11 +1430,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/exenv": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
-      "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
-    },
     "node_modules/fast-deep-equal": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -1795,14 +1785,6 @@
       "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
       "dev": true
     },
-    "node_modules/jwt-decode": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
-      "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
-      "engines": {
-        "node": ">=18"
-      }
-    },
     "node_modules/keyv": {
       "version": "4.5.4",
       "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -1933,14 +1915,6 @@
       "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
       "dev": true
     },
-    "node_modules/object-assign": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/once": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -2100,16 +2074,6 @@
         "node": ">= 0.8.0"
       }
     },
-    "node_modules/prop-types": {
-      "version": "15.8.1",
-      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
-      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
-      "dependencies": {
-        "loose-envify": "^1.4.0",
-        "object-assign": "^4.1.1",
-        "react-is": "^16.13.1"
-      }
-    },
     "node_modules/punycode": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
@@ -2139,6 +2103,36 @@
         }
       ]
     },
+    "node_modules/rc-slider": {
+      "version": "10.5.0",
+      "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.5.0.tgz",
+      "integrity": "sha512-xiYght50cvoODZYI43v3Ylsqiw14+D7ELsgzR40boDZaya1HFa1Etnv9MDkQE8X/UrXAffwv2AcNAhslgYuDTw==",
+      "dependencies": {
+        "@babel/runtime": "^7.10.1",
+        "classnames": "^2.2.5",
+        "rc-util": "^5.27.0"
+      },
+      "engines": {
+        "node": ">=8.x"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
+    "node_modules/rc-util": {
+      "version": "5.38.1",
+      "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.38.1.tgz",
+      "integrity": "sha512-e4ZMs7q9XqwTuhIK7zBIVFltUtMSjphuPPQXHoHlzRzNdOwUxDejo0Zls5HYaJfRKNURcsS/ceKVULlhjBrxng==",
+      "dependencies": {
+        "@babel/runtime": "^7.18.3",
+        "react-is": "^18.2.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.9.0",
+        "react-dom": ">=16.9.0"
+      }
+    },
     "node_modules/react": {
       "version": "18.2.0",
       "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
@@ -2163,39 +2157,16 @@
       }
     },
     "node_modules/react-is": {
-      "version": "16.13.1",
-      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
-      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
-    },
-    "node_modules/react-lifecycles-compat": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
-      "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
-    },
-    "node_modules/react-modal": {
-      "version": "3.16.1",
-      "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz",
-      "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==",
-      "dependencies": {
-        "exenv": "^1.2.0",
-        "prop-types": "^15.7.2",
-        "react-lifecycles-compat": "^3.0.0",
-        "warning": "^4.0.3"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "peerDependencies": {
-        "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18",
-        "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18"
-      }
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+      "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
     },
     "node_modules/react-router": {
-      "version": "6.20.1",
-      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.20.1.tgz",
-      "integrity": "sha512-ccvLrB4QeT5DlaxSFFYi/KR8UMQ4fcD8zBcR71Zp1kaYTC5oJKYAp1cbavzGrogwxca+ubjkd7XjFZKBW8CxPA==",
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.18.0.tgz",
+      "integrity": "sha512-vk2y7Dsy8wI02eRRaRmOs9g2o+aE72YCx5q9VasT1N9v+lrdB79tIqrjMfByHiY5+6aYkH2rUa5X839nwWGPDg==",
       "dependencies": {
-        "@remix-run/router": "1.13.1"
+        "@remix-run/router": "1.11.0"
       },
       "engines": {
         "node": ">=14.0.0"
@@ -2205,12 +2176,12 @@
       }
     },
     "node_modules/react-router-dom": {
-      "version": "6.20.1",
-      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.20.1.tgz",
-      "integrity": "sha512-npzfPWcxfQN35psS7rJgi/EW0Gx6EsNjfdJSAk73U/HqMEJZ2k/8puxfwHFgDQhBGmS3+sjnGbMdMSV45axPQw==",
+      "version": "6.18.0",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.18.0.tgz",
+      "integrity": "sha512-Ubrue4+Ercc/BoDkFQfc6og5zRQ4A8YxSO3Knsne+eRbZ+IepAsK249XBH/XaFuOYOYr3L3r13CXTLvYt5JDjw==",
       "dependencies": {
-        "@remix-run/router": "1.13.1",
-        "react-router": "6.20.1"
+        "@remix-run/router": "1.11.0",
+        "react-router": "6.18.0"
       },
       "engines": {
         "node": ">=14.0.0"
@@ -2220,6 +2191,11 @@
         "react-dom": ">=16.8"
       }
     },
+    "node_modules/regenerator-runtime": {
+      "version": "0.14.1",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+      "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+    },
     "node_modules/resolve-from": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -2458,14 +2434,6 @@
         "node": ">=14.17"
       }
     },
-    "node_modules/undici-types": {
-      "version": "5.26.5",
-      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
-      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
-      "dev": true,
-      "optional": true,
-      "peer": true
-    },
     "node_modules/uri-js": {
       "version": "4.4.1",
       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -2530,14 +2498,6 @@
         }
       }
     },
-    "node_modules/warning": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
-      "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
-      "dependencies": {
-        "loose-envify": "^1.0.0"
-      }
-    },
     "node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -2576,6 +2536,14 @@
       "funding": {
         "url": "https://github.com/sponsors/sindresorhus"
       }
+    },
+    "node_modules/zod": {
+      "version": "3.22.4",
+      "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz",
+      "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==",
+      "funding": {
+        "url": "https://github.com/sponsors/colinhacks"
+      }
     }
   }
 }
diff --git a/growbros-frontend/package.json b/growbros-frontend/package.json
index 12710de1d735108819a3d939ab2205e29a287e80..7ca6c4475f64bf1dd3840f71542f0f217fa4ec98 100644
--- a/growbros-frontend/package.json
+++ b/growbros-frontend/package.json
@@ -11,16 +11,15 @@
   },
   "dependencies": {
     "font-awesome": "^4.7.0",
-    "jwt-decode": "^4.0.0",
+    "rc-slider": "^10.5.0",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
-    "react-modal": "^3.16.1",
-    "react-router-dom": "^6.18.0"
+    "react-router-dom": "^6.18.0",
+    "zod": "^3.22.4"
   },
   "devDependencies": {
     "@types/react": "^18.2.15",
     "@types/react-dom": "^18.2.7",
-    "@types/react-modal": "^3.16.3",
     "@typescript-eslint/eslint-plugin": "^6.0.0",
     "@typescript-eslint/parser": "^6.0.0",
     "@vitejs/plugin-react-swc": "^3.3.2",
diff --git a/growbros-frontend/public/recources/images/Broccoli.webp b/growbros-frontend/public/recources/images/Broccoli.webp
new file mode 100644
index 0000000000000000000000000000000000000000..ff2de7e70d996843a3a2ac87b3e19caa2ed53b68
Binary files /dev/null and b/growbros-frontend/public/recources/images/Broccoli.webp differ
diff --git a/growbros-frontend/public/recources/images/Cucumber.webp b/growbros-frontend/public/recources/images/Cucumber.webp
new file mode 100644
index 0000000000000000000000000000000000000000..e1f69eafcac7d2b010c14543bfa6d2e333999fc7
Binary files /dev/null and b/growbros-frontend/public/recources/images/Cucumber.webp differ
diff --git a/growbros-frontend/public/recources/images/Grandma.png b/growbros-frontend/public/recources/images/Grandma.png
new file mode 100644
index 0000000000000000000000000000000000000000..439902b11c22fabff36a284cd70930d627bbd978
Binary files /dev/null and b/growbros-frontend/public/recources/images/Grandma.png differ
diff --git a/growbros-frontend/public/recources/images/Red_Vegetable.webp b/growbros-frontend/public/recources/images/Red_Vegetable.webp
new file mode 100644
index 0000000000000000000000000000000000000000..e33fa6c70398d20fac7d1dbc5cc26ebfb6d6eac3
Binary files /dev/null and b/growbros-frontend/public/recources/images/Red_Vegetable.webp differ
diff --git a/growbros-frontend/public/recources/images/Vegetables.jpeg b/growbros-frontend/public/recources/images/Vegetables.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..978db4457b0a40315581c5de88b2c87ae0052c44
Binary files /dev/null and b/growbros-frontend/public/recources/images/Vegetables.jpeg differ
diff --git a/growbros-frontend/public/vite.svg b/growbros-frontend/public/vite.svg
deleted file mode 100644
index d208b4573c4985b797c6ff570335460ef4720a37..0000000000000000000000000000000000000000
--- a/growbros-frontend/public/vite.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img"
-     class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257">
-    <defs>
-        <linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%">
-            <stop offset="0%" stop-color="#41D1FF"></stop>
-            <stop offset="100%" stop-color="#BD34FE"></stop>
-        </linearGradient>
-        <linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%">
-            <stop offset="0%" stop-color="#FFEA83"></stop>
-            <stop offset="8.333%" stop-color="#FFDD35"></stop>
-            <stop offset="100%" stop-color="#FFA800"></stop>
-        </linearGradient>
-    </defs>
-    <path fill="url(#IconifyId1813088fe1fbc01fb466)"
-          d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path>
-    <path fill="url(#IconifyId1813088fe1fbc01fb467)"
-          d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path>
-</svg>
\ No newline at end of file
diff --git a/growbros-frontend/src/App.tsx b/growbros-frontend/src/App.tsx
index 2e7acd837b6f56bd2ea23654ae9714001507f5f1..fe6ec4f489cf36a18e980bcf08593d1c7b44a187 100644
--- a/growbros-frontend/src/App.tsx
+++ b/growbros-frontend/src/App.tsx
@@ -2,41 +2,24 @@ import "./App.css";
 import Home from "./pages/Home";
 import Garten from "./pages/Garten";
 import Suche from "./pages/Suche";
-import {Routes, Route} from "react-router-dom";
+import Navbar from "./components/Navbar";
+import {Route, Routes} from "react-router-dom";
 import Wunschliste from "./pages/Wunschliste";
 import PlantDetails from "./components/PlantDetails";
-import Navbar from "./components/Navbar.tsx";
-import NavbarRegistrationAndLogin from "./components/NavbarRegistrationAndLogin.tsx";
-import {useState} from "react";
-import {checkJwtStatus, deleteJwtCookie} from "./jwt/Cookies.ts";
-import Login from "./pages/Login.tsx";
-import Register from "./pages/Register.tsx";
 
 function App() {
-  const [isLoggedIn, setIsLoggedIn] = useState(false);
-
-  checkJwtStatus(setIsLoggedIn);
-
-  const handleLogout = async () => {
-    deleteJwtCookie();
-    setIsLoggedIn(false);
-  };
-
-  return (
-    <div className="App">
-      {isLoggedIn ? <Navbar onLogout={handleLogout} /> : <NavbarRegistrationAndLogin />}
-      <Routes>
-        <Route path="/" element={<Home />} />
-        <Route path="/garten" element={<Garten />} />
-        <Route path="/wunschliste" element={<Wunschliste />} />
-        <Route path="/suchen" element={<Suche />} />
-        <Route path="/pflanze/:plantId" element={<PlantDetails />} />
-        <Route path="/register" element={<Register />} />
-        <Route path="/login" element={<Login />} />
-      </Routes>
-
-    </div>
-  );
+    return (
+        <div className="App">
+            <Navbar/>
+            <Routes>
+                <Route path="/" element={<Home/>}/>
+                <Route path="/garten" element={<Garten/>}/>
+                <Route path="/wunschliste" element={<Wunschliste/>}/>
+                <Route path="/suchen" element={<Suche/>}/>
+                <Route path="/pflanze/:plantId" element={<PlantDetails/>}/>
+            </Routes>
+        </div>
+    );
 }
 
 export default App;
diff --git a/growbros-frontend/src/components/DropDownFilter.tsx b/growbros-frontend/src/components/DropDownFilter.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0520b745847527544a2ab420741d892b38d1111e
--- /dev/null
+++ b/growbros-frontend/src/components/DropDownFilter.tsx
@@ -0,0 +1,32 @@
+import { useState } from "react";
+import { propsDropDownFilter } from "../utils/commonTypes";
+
+function DropDownFilter(props: propsDropDownFilter) {
+ 
+        const options = props.options;
+        const topic = props.topic;
+        const [selectedOption, setSelectedOption] = useState("");
+      
+        const handleOptionChange = (event: any) => {
+          setSelectedOption(event.target.value);
+        };
+      
+        return (
+          <div >
+            <label>{topic}</label>
+            <select value={selectedOption} onChange={handleOptionChange}>
+              <option value=""></option>
+              {options.map((option, index) => (
+                <option key={index} value={option}>
+                  {option}
+                </option>
+              ))}
+            </select>
+          </div>
+        );
+      }
+      
+      
+
+export default DropDownFilter
+
diff --git a/growbros-frontend/src/components/FilterPage.tsx b/growbros-frontend/src/components/FilterPage.tsx
index 61b7bdd51e708a5bfd2b2653e4bcc1b0dcf37813..ebee59dab028ce2e01f08388bebc5bf5d6c21fc5 100644
--- a/growbros-frontend/src/components/FilterPage.tsx
+++ b/growbros-frontend/src/components/FilterPage.tsx
@@ -1,34 +1,67 @@
-
+import { useState } from "react";
+import Slider from "rc-slider";
+import "rc-slider/assets/index.css";
+import "../stylesheets/FilterPage.css";
+import DropDownFilter from "./DropDownFilter";
+import { propsSliderFilter } from "../utils/commonTypes";
 
 function FilterPage() {
   return (
-    <div className="filterPage">
-      <h3>Setze Filter und suche nach passenden Pflanzen</h3>
-    </div>
+    <>
+      <div className="filterPage">
+        <h3>Setze Filter und suche nach passenden Pflanzen</h3>
+      </div>
+      <div>
+        <DropDownFilter
+          topic={"Wasserbedarf "}
+          options={["Trocken", "Feucht", "Sehr Feucht"]}
+        />
+        <DropDownFilter
+          topic={"Nährstoffbedarf "}
+          options={["Niedrig", "Mittel", "Hoch"]}
+        />
+        <DropDownFilter
+          topic={"Lichtbedarf "}
+          options={["Niedrig", "Mittel", "Hoch"]}
+        />
+        <DropDownFilter
+          topic={"Bodentyp"}
+          options={["Leicht", "Mittel", "Schwer"]}
+        />
+      </div>
+      <SliderFilter topic={"Anbauphase"} min={1} max={52} />
+      <SliderFilter topic={"Erntezeitraum"} min={1} max={52} />
+      <SliderFilter topic={"Wachstumsdauer"} min={1} max={52} />{" "}
+    </>
   );
 }
 
-/*function Filter() {
-  const options = ["Option 1", "Option 2", "Option 3"];
-  const [selectedOption, setSelectedOption] = useState("");
 
-  const handleOptionChange = (event) => {
-    setSelectedOption(event.target.value);
+
+
+function SliderFilter({ topic, min, max }: propsSliderFilter) {
+  const [range, setRange] = useState([min, max]);
+
+  const handleRangeChange = (newRange: any) => {
+    setRange(newRange);
   };
 
   return (
-    <>
-      <label>Wählen Sie eine Option:</label>
-      <select value={selectedOption} onChange={handleOptionChange}>
-        <option value="">-- Bitte wählen --</option>
-        {options.map((option, index) => (
-          <option key={index} value={option}>
-            {option}
-          </option>
-        ))}
-      </select>
-    </>
+    <div>
+      <label>
+        {topic} von KW {range[0]} bis KW {range[1]}
+      </label>
+      <Slider
+        min={min}
+        max={max}
+        range
+        value={range}
+        onChange={handleRangeChange}
+      />
+    </div>
   );
-}*/
+}
+
 
 export default FilterPage;
+
diff --git a/growbros-frontend/src/components/Grandma.tsx b/growbros-frontend/src/components/Grandma.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c582a61c491fa11e2f445cf7e70a10e0de3ee10d
--- /dev/null
+++ b/growbros-frontend/src/components/Grandma.tsx
@@ -0,0 +1,12 @@
+function Grandma(props: any) {
+  const grandmaInfo: String = props.grandmaInfo;
+
+  return (
+    <div>
+      <img src="../../public/recources/images/Grandma.png"></img>
+      <div className="grandmaInfo">{grandmaInfo}</div>
+    </div>
+  );
+}
+
+export default Grandma;
diff --git a/growbros-frontend/src/components/PlantCard.tsx b/growbros-frontend/src/components/PlantCard.tsx
index ecba391baccb4bfc43f6d5156acd480197218abe..5e1afa9f250cb610990219c0ce1e3006fb5a7bc2 100644
--- a/growbros-frontend/src/components/PlantCard.tsx
+++ b/growbros-frontend/src/components/PlantCard.tsx
@@ -1,8 +1,9 @@
 import "../stylesheets/PlantCard.css";
 import { NavLink } from "react-router-dom";
+import { Plant } from "../utils/schemas";
 
 export default function PlantCard(props: any) {
-  const plant = props.plant;
+  const plant: Plant= props.plant;
 
   return (
     <>
diff --git a/growbros-frontend/src/components/PlantDetails.tsx b/growbros-frontend/src/components/PlantDetails.tsx
index ba97abc1995e4a2cecb620a22e49fc932c196535..18fde841b16b19591009ce21197beb39b55fa16a 100644
--- a/growbros-frontend/src/components/PlantDetails.tsx
+++ b/growbros-frontend/src/components/PlantDetails.tsx
@@ -1,8 +1,12 @@
 import "../stylesheets/PlantDetails.css";
 import "font-awesome/css/font-awesome.min.css";
+import { useState } from "react";
+import { Plant, PlantSchema } from "../utils/schemas";
+
+//TODO translateEnums fixen
 
 function PlantDetails(props: any) {
-  const plant = props.plant;
+  const plant: Plant = PlantSchema.parse(props.plant);
 
   return (
     <>
@@ -40,11 +44,11 @@ function PlantDetails(props: any) {
           </div>
           <div className="infoBox">
             <div className="title">Bodentyp</div>
-            <p>{plant.groundType}</p>
+            {plant.groundType}
           </div>
           <div className="infoBox">
             <div className="title">Nährstoffbedarf</div>
-            <p>{plant.nutrientDemand}</p>
+            {plant.nutrientDemand}
           </div>
           <div className="infoBox">
             <div className="title">Wasserbedarf</div>
@@ -63,27 +67,104 @@ function PlantDetails(props: any) {
             margin: "0 0 40px 0",
           }}
         >
-          <ButtonAddToGarden></ButtonAddToGarden>
-          <ButtonAddToWishlist></ButtonAddToWishlist>
+          <ButtonAddToGarden plantId={plant.id}></ButtonAddToGarden>
+          <ButtonAddToWishlist plantId={plant.id}></ButtonAddToWishlist>
         </div>
       </div>
     </>
   );
 }
 
-function ButtonAddToGarden() {
+function ButtonAddToGarden({ plantId }: any) {
+  const [status, setStatus] = useState<null | String>(null);
+  const token: String = "";
+
+  const handleButtonClick = async () => {
+    try {
+      const response = await fetch(
+        `http://localhost:8080/api/v1/garden/add/${plantId}`,
+        {
+          method: "POST",
+          headers: {
+            "Content-Type": "application/json",
+            Authorization: `Bearer ${token}`,
+          },
+        }
+      );
+      if (response.status === 201) {
+        console.log("Pflanze wurde erfolgreich dem Garten hinzugefügt");
+      } else {
+        console.log("Unexpected response status:", response.status);
+        setStatus("Pflanze konnte nicht dem Garten hinzugefügt werden");
+      }
+    } catch (error) {
+      console.error("Error", error);
+      setStatus("Pflanze konnte nicht dem Garten hinzugefügt werden");
+    }
+  };
+
   return (
-    <button>
-      <i className="fa fa-leaf"></i>
-    </button>
+    <>
+      {status && (
+        <div
+          className={`status-message ${
+            status.includes("erfolgreich") ? "success-message" : "error-message"
+          }`}
+        >
+          {status}
+        </div>
+      )}
+      <button onClick={handleButtonClick}>
+        <i className="fa fa-leaf"></i>
+      </button>
+    </>
   );
 }
 
-function ButtonAddToWishlist() {
+//TODO css für status message
+function ButtonAddToWishlist({ plantId }: any) {
+  const [status, setStatus] = useState<null | String>(null);
+  const token: String = "";
+
+  const handleButtonClick = async () => {
+    try {
+      const response = await fetch(
+        `http://localhost:8080/api/v1/wishlist/add/${plantId}`,
+        {
+          method: "POST",
+          headers: {
+            "Content-Type": "application/json",
+            Authorization: `Bearer ${token}`,
+          },
+        }
+      );
+      if (response.status === 201) {
+        console.log("Pflanze wurde erfolgreich der Wunschliste hinzugefügt");
+      } else {
+        setStatus("Pflanze konnte nicht der Wunschliste hinzugefügt werden");
+      }
+    } catch (error) {
+      console.error("Error", error);
+      setStatus("Pflanze konnte nicht der Wunschliste hinzugefügt werden");
+    }
+  };
+
   return (
-    <button>
-      <i className="fa fa-heart"></i>
-    </button>
+    <>
+      {status && (
+        <div
+          className={`status-message ${
+            status.includes("erfolgreich") ? "success-message" : "error-message"
+          }`}
+        >
+          {" "}
+          {status}
+        </div>
+      )}
+      <button onClick={handleButtonClick}>
+        <i className="fa fa-heart"></i>
+      </button>
+    </>
   );
 }
 
diff --git a/growbros-frontend/src/components/PlantsOverview.tsx b/growbros-frontend/src/components/PlantsOverview.tsx
index f3923e3b9e65f6a498088ee292f71a59ac7026e5..46d60b832851e6d7666968a069bb79a6af909bd3 100644
--- a/growbros-frontend/src/components/PlantsOverview.tsx
+++ b/growbros-frontend/src/components/PlantsOverview.tsx
@@ -1,8 +1,11 @@
-import { useEffect, useState } from "react";
+
 import PlantCard from "./PlantCard";
+import { plant } from "../utils/commonTypes";
+
+export default function PlantsOverview(props: any) {
+  const plants: plant[] = props.plants;
 
-export default function PlantsOverview() {
-  const [plants, setPlants] = useState<any[]>([]);
+  /*const [plants, setPlants] = useState<any[]>([]);
   const [error, setError] = useState();
 
   useEffect(() => {
@@ -10,24 +13,16 @@ export default function PlantsOverview() {
       .then((res) => res.json())
       .then((plants) => setPlants(plants))
       .catch((err) => setError(err));
-  }, []);
+  }, []);*/
 
   return (
     <>
-      {error ? (
-        <p>Error fetching data</p>
-      ) : (
-        <ul style={{ display: "flex", gap: "1rem", width: "100%" }}>
-          {plants?.map((plant) => (
-            <PlantCard plant={plant} key={plant.id} />
-          ))}
-        </ul>
-      )}
+      <ul style={{ display: "flex", gap: "1rem", width: "100%" }}>
+        {plants.map((plant) => (
+          <PlantCard plant={plant} key={plant.id} />
+        ))}
+      </ul>
     </>
   );
 }
 
-
-
-
-
diff --git a/growbros-frontend/src/env.d.ts b/growbros-frontend/src/env.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb538c1ae91f4ace2cfe17c2413b8b60df5fb198
--- /dev/null
+++ b/growbros-frontend/src/env.d.ts
@@ -0,0 +1,7 @@
+interface ImportMetaEnv {
+    readonly VITE_GROWBROS_BACKEND_URL: string
+}
+
+interface ImportMeta {
+    readonly env: ImportMetaEnv
+}
diff --git a/growbros-frontend/src/pages/BackendConnectorTestInterface.tsx b/growbros-frontend/src/pages/BackendConnectorTestInterface.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b28b5617d910a39409a8daca7b2e009cdff462b4
--- /dev/null
+++ b/growbros-frontend/src/pages/BackendConnectorTestInterface.tsx
@@ -0,0 +1,34 @@
+import {BackendConnectorImpl} from "../utils/BackendConnectorImpl.ts";
+
+const bc = new BackendConnectorImpl("http://localhost:8080/api/v1");
+
+export function BackendConnectorTestInterface() {
+    return <div style={{padding: "1rem"}}>
+        <h2>Backend connector test</h2>
+        <p>Achtung: das ist / war ausschließlich zum Testen von meinen geschriebenen fetch-methoden. Benutzt das auf
+            keinen Fall in euren components... lg lukas</p>
+        <h3>Plants controller</h3>
+        <ul style={{display: "block", listStyleType: "initial"}}>
+            <li onClick={async () => console.log(await bc.getSinglePlant(1101))}>Get single plant</li>
+            <li onClick={async () => console.log(await bc.getAllPlants())}>Get all plants</li>
+            <li onClick={async () => console.log(await bc.getRandomPlants(5))}>Get random plants</li>
+            <li onClick={async () => console.log(await bc.searchPlants({searchTerm: "Salat"}))}>Search for "salat"</li>
+        </ul>
+        <h3>Garden controller</h3>
+        <ul style={{display: "block", listStyleType: "initial"}}>
+            <li onClick={async () => console.log(await bc.getGardenEntries())}>Get garden</li>
+            <li onClick={async () => console.log(await bc.addToGarden(1000))}>Add plant to garden</li>
+            <li onClick={async () => console.log(await bc.getGardenSize())}>garden size</li>
+            <li onClick={async () => console.log(await bc.removeEntryFromGarden(3))}>remove entry</li>
+            <li onClick={async () => console.log(await bc.clearGarden())}>clear garden</li>
+        </ul>
+        <h3>Wishlist controller</h3>
+        <ul style={{display: "block", listStyleType: "initial"}}>
+            <li onClick={async () => console.log(await bc.addToWishlist(1000))}>add to wishlist</li>
+            <li onClick={async () => console.log(await bc.clearWishlist())}>clear wishlist</li>
+            <li onClick={async () => console.log(await bc.removeFromWishlist(1))}>remove from wishlist</li>
+            <li onClick={async () => console.log(await bc.getWishlistEntries())}>get wishlist entries</li>
+            <li onClick={async () => console.log(await bc.getWishlistSize())}>get wishlist size</li>
+        </ul>
+    </div>
+}
diff --git a/growbros-frontend/src/pages/Garten.tsx b/growbros-frontend/src/pages/Garten.tsx
index 00a28f876d08548f1044185b553f09f398bf4cb4..041aa00e16fd24165e17d853dea2b08dd19c6391 100644
--- a/growbros-frontend/src/pages/Garten.tsx
+++ b/growbros-frontend/src/pages/Garten.tsx
@@ -1,10 +1,23 @@
-import PlantsOverview from "../components/PlantsOverview";
+import DropDownFilter from "../components/DropDownFilter";
+import PlantDetails from "../components/PlantDetails";
 
 function Garten() {
   return (
     <div>
       <h2>Dein Garten</h2>
-      <PlantsOverview />
+      <DropDownFilter
+        topic={"Sortierung der Pflanzen im Garten"}
+        options={[
+          "neueste zuerst",
+          "als nächstes anpflanzbar",
+          "als nächstes erntbar",
+        ]}
+      />
+      <PlantDetails
+        plant={JSON.parse(
+          '{"id":1,"name":"Salat (Gartensalat)","latinName":"Lactuca sativa var. crispa","growingTips":"Salate eignen sich sehr gut als ‚Lückenfüller‘. Sie benötigen ausreichend Feuchtigkeit und haben einen vergleichsweise geringen Nährstoffbedarf. Durch eine geschickte Auswahl lassen sich Salate das ganze Jahr über anbauen: im Frühjahr und Frühsommer Kopf- und Schnitt-/Pflücksalate; im Sommer und Herbst Zichoriensalate und Eissalate sowie Feldsalat (v.a. im Herbst, Winter). Für eine kontinuierliche Ernte am besten in zeitlichen Abständen säen bzw. pflanzen. Arten und Sorten müssen dabei an die jeweilige Jahreszeit angepasst sein, z.B. beginnen Frühjahrssorten bei zu viel Hitze zu schießen. Dabei bildet sich ein langer Stiel und die Blätter werden bitter. Nach einigen Wochen kommen oben kleine Blüten zum Vorschein, woraus sich viele halbmondförmige Samen bilden. Diese können für das Folgejahr abgesammelt werden oder verteilen sich selbst im Beet, wenn du sie stehen lässt.","description":"Salat steht als Überbegriff für viele Blattgemüse. Kopfsalate bilden - wie der Name schon sagt - einen Kopf und werden am Stück geerntet. Pflücksalate kann man kontinuierlich ernten, wenn man jeweils nur einzelne Blätter abpflückt. ","origin":"Gartensalate sind gezüchtete Lattichgewächse (Lactuca sativa) mit Urpsrung in Südeuropa, Nordafrika und Indien. Darunter fallen Kopfsalate (Batavia, Eissalat), Schnitt-/Pflücksalate (Lollo Rosso/Bionda, Eichblatt) und Römersalate.","plantWeekStart":10,"plantWeekEnd":40,"harvestWeekStart":15,"harvestWeekEnd":44,"growthDuration":6,"nutrientDemand":"MEDIUM","lightingDemand":"MEDIUM","waterDemand":"WET","groundType":null,"imageUrl":"https://d3t240q2dksnz7.cloudfront.net/a4cbb94a099179235fdd5696ae5f3833.jpg"}'
+        )}
+      />
     </div>
   );
 }
diff --git a/growbros-frontend/src/pages/Home.tsx b/growbros-frontend/src/pages/Home.tsx
index 78a92920d081c3543b05fcfd20f1b63c9a1bd50e..30c0b80cb82b81777e0a1fd82237e0b087f1e923 100644
--- a/growbros-frontend/src/pages/Home.tsx
+++ b/growbros-frontend/src/pages/Home.tsx
@@ -7,7 +7,7 @@ function Home() {
     <main>
       <div className="hero">
         <img
-          src="https://images.pexels.com/photos/2611818/pexels-photo-2611818.jpeg"
+          src="../../public/recources/images/Vegetables.jpeg"
           className="mainPicture"
         ></img>
         <div className="descriptionAside">
@@ -19,7 +19,7 @@ function Home() {
             verwalte sie mühelos. Starte noch heute und lass deinen Garten in
             voller Blüte erstrahlen!"
           </p>
-          <Link></Link>
+          <StartNowLink></StartNowLink>
         </div>
       </div>
       <div className="secondDiv">
@@ -37,14 +37,14 @@ function Home() {
         </div>
         <img
           className="smallPicture"
-          src="https://images.unsplash.com/photo-1615485021022-dec8994adeba?auto=format&fit=crop&q=60&w=1000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTh8fHZlZ2V0YWJsZXMlMjB3aGl0ZSUyMGJhY2tncm91bmR8ZW58MHx8MHx8fDA%3D"
+          src="../../public/recources/images/Broccoli.webp"
         ></img>
       </div>
 
       <div style={{ display: "flex" }}>
         <img
           className="smallPicture"
-          src="https://images.unsplash.com/photo-1587486912758-4367d2015d6c?auto=format&fit=crop&q=60&w=1000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTR8fHZlZ2V0YWJsZXMlMjB3aGl0ZSUyMGJhY2tncm91bmR8ZW58MHx8MHx8fDA%3D"
+          src="../../public/recources/images/Red_Vegetable.webp"
         ></img>
         <div className="smallDiv">
           <p>
@@ -65,14 +65,14 @@ function Home() {
         </div>
         <img
           className="smallPicture"
-          src="https://images.unsplash.com/photo-1587411768638-ec71f8e33b78?auto=format&fit=crop&q=60&w=1000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTJ8fHZlZ2V0YWJsZXMlMjB3aGl0ZSUyMGJhY2tncm91bmR8ZW58MHx8MHx8fDA%3D"
+          src="../../public/recources/images/Cucumber.webp"
         ></img>
       </div>
     </main>
   );
 }
 
-function Link() {
+function StartNowLink() {
   return (
     <div className="link">
       <NavLink to="/suchen">
diff --git a/growbros-frontend/src/pages/Suche.tsx b/growbros-frontend/src/pages/Suche.tsx
index a3f068fbb618930017f162de734b2d8c8d92acc0..fd8029eedaa140d23d3ff32b41b4454a8ca710aa 100644
--- a/growbros-frontend/src/pages/Suche.tsx
+++ b/growbros-frontend/src/pages/Suche.tsx
@@ -1,14 +1,52 @@
 import "font-awesome/css/font-awesome.min.css";
 import "../stylesheets/Suche.css";
 import PlantsOverview from "../components/PlantsOverview";
-import { useState } from "react";
+import { useState, useEffect } from "react";
 import FilterPage from "../components/FilterPage";
+import { Plant } from "../utils/schemas";
 
 function Suche() {
+  const [randomPlants, setRandomPlants] = useState<Plant[] | null>(null);
+  const [error, setError] = useState<null | String>(null);
+  const randomPlantsCount: number = 30;
+  const token: String = "";
+
+  const fetchRandomPlants = async () => {
+    try {
+      const response = await fetch(
+        `http://localhost:8080/api/v1/plants/randomPlants/${randomPlantsCount}`,
+        {
+          method: "GET",
+          headers: {
+            "Content-Type": "application/json",
+            Authorization: `Bearer ${token}`,
+          },
+        }
+      );
+      if (response.status == 200) {
+        const data = await response.json();
+        setRandomPlants(data);
+        console.log("Succesfully fetched data");
+      } else {
+        console.log("Unexpected response status:", response.status);
+        setError("Error fetching data");
+      }
+    } catch (error) {
+      console.error("Error", error);
+      setError("Error fetching data");
+    }
+  };
+
+  useEffect(() => {
+    fetchRandomPlants();
+  }, []);
+
   return (
     <>
       <SearchBar />
-      <PlantsOverview />
+      <div>
+        {error ? <div>{error}</div> : <PlantsOverview plants={randomPlants} />}
+      </div>
     </>
   );
 }
diff --git a/growbros-frontend/src/pages/Wunschliste.tsx b/growbros-frontend/src/pages/Wunschliste.tsx
index 18e7ea8ef8c3da3ddcbb7be5f6435b94bff0562e..cfb7d4ce248613e78bf8e57414ab321a66e5a2e2 100644
--- a/growbros-frontend/src/pages/Wunschliste.tsx
+++ b/growbros-frontend/src/pages/Wunschliste.tsx
@@ -1,8 +1,9 @@
 import { useEffect, useState } from "react";
 import PlantDetails from "../components/PlantDetails";
+import { Plant } from "../utils/schemas";
 
 function Wunschliste() {
-  const [plants, setPlants] = useState<any[]>([]);
+  const [plants, setPlants] = useState<Plant[] | null>(null);
   const [error, setError] = useState();
 
   useEffect(() => {
diff --git a/growbros-frontend/src/stylesheets/FilterPage.css b/growbros-frontend/src/stylesheets/FilterPage.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/growbros-frontend/src/utils/BackendConnectorImpl.ts b/growbros-frontend/src/utils/BackendConnectorImpl.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d2f32290a1dec45c43072f774c9cff9c652e0324
--- /dev/null
+++ b/growbros-frontend/src/utils/BackendConnectorImpl.ts
@@ -0,0 +1,281 @@
+import {IBackendConnector} from "./IBackendConnector.ts";
+import {CustomPlantPage, CustomPlantPageSchema, Plant, PlantSchema, SearchRequest} from "./schemas.ts";
+import {ZodError} from "zod";
+import {FetchResult} from "./FetchResult.ts";
+import {HttpMethod} from "./commonTypes";
+
+export class BackendConnectorImpl implements IBackendConnector {
+    private readonly baseUrl: string;
+
+    constructor(baseUrl: string) {
+        const lastSlash = baseUrl.lastIndexOf("/");
+        const endsWithSlash = lastSlash === baseUrl.length - 1;
+        if (endsWithSlash) {
+            baseUrl = baseUrl.substring(0, lastSlash)
+        }
+        this.baseUrl = baseUrl;
+    }
+
+    async getAllPlants(page?: number, pageSize?: number): Promise<FetchResult<CustomPlantPage>> {
+        let result: FetchResult<CustomPlantPage> = {};
+        try {
+            const pageParam = page ? `page=${page}&` : "";
+            const pageSizeParam = pageSize ? `pageSize=${pageSize}` : "";
+            const response = await this.makeFetchWithAuth("/plants?" + pageParam + pageSizeParam);
+            const json = await response.json();
+            result = this.parsePlantsFromPage(json);
+        } catch (e) {
+            console.error("An error occurred while fetching all plants")
+            console.error(e);
+            result = {...result, err: e};
+        }
+        return result;
+    }
+
+    async searchPlants(search: SearchRequest): Promise<FetchResult<Plant[]>> {
+        let result: FetchResult<Plant[]> = {};
+        try {
+            const searchParams = new URLSearchParams(
+                Object.entries(search)
+                    .map(([key, value]) => [key, value as string]));
+            const response = await this.makeFetchWithAuth("/plants/search?" + searchParams);
+            const json = await response.json();
+            result = this.parsePlants(json);
+        } catch (e) {
+            console.error("An error occurred while searching through plants")
+            console.error(e);
+            result = {...result, err: e};
+        }
+        return result;
+    }
+
+    async getRandomPlants(amount: number): Promise<FetchResult<Plant[]>> {
+        let result: FetchResult<Plant[]> = {};
+        try {
+            const response = await this.makeFetchWithAuth("/plants/randomPlants/" + amount);
+            const json = await response.json();
+            result = this.parsePlants(json);
+        } catch (e) {
+            console.error("An error occurred while getting random plants")
+            console.error(e);
+            result = {...result, err: e};
+        }
+        return result;
+    }
+
+    async getSinglePlant(id: number): Promise<FetchResult<Plant | null>> {
+        let result: FetchResult<Plant> = {};
+        try {
+            const response = await this.makeFetchWithAuth("/plants/" + id);
+            const json = await response.json();
+            result = this.parseSinglePlant(json);
+        } catch (e) {
+            console.error("An error occurred while fetching plant with ID", id);
+            console.error(e);
+            result = {...result, err: e};
+        }
+        return result;
+    }
+
+    async addToGarden(plantId: number): Promise<FetchResult<void>> {
+        let result: FetchResult<void> = {};
+        try {
+            await this.makeFetchWithAuthAndOptions("/garden/add/" + plantId, {method: "POST"});
+        } catch (e) {
+            console.error("An error occurred while adding plant with ID", plantId, "to garden");
+            console.error(e);
+            result = {err: e};
+        }
+        return result;
+    }
+
+    async clearGarden(): Promise<FetchResult<number>> {
+        let result: FetchResult<number>;
+        try {
+            const res = await this.makeFetchWithAuthAndOptions("/garden/remove/all", {method: "DELETE"});
+            const num = await res.json();
+            result = {value: num};
+        } catch (e) {
+            console.error("An error occurred while clearing garden");
+            console.error(e);
+            result = {err: e};
+        }
+        return result;
+    }
+
+    async getGardenEntries(sort?: string): Promise<FetchResult<Plant[]>> {
+        let result: FetchResult<Plant[]> = {};
+        try {
+            const params = new URLSearchParams();
+            if (sort) params.set("sort", sort);
+            const response = await this.makeFetchWithAuth("/garden" + params);
+            const json = await response.json();
+            result = this.parsePlants(json);
+        } catch (e) {
+            console.error("An error occurred while getting garden entries")
+            console.error(e);
+            result = {...result, err: e};
+        }
+        return result;
+    }
+
+    async getGardenSize(): Promise<FetchResult<number>> {
+        let result: FetchResult<number> = {};
+        try {
+            const response = await this.makeFetchWithAuth("/garden/count");
+            const json = await response.json();
+            const size = Number.parseInt(json);
+            result = {value: size};
+        } catch (e) {
+            console.error("An error occurred while fetching garden size")
+            console.error(e);
+            result = {...result, err: e};
+        }
+        return result;
+    }
+
+    async removeEntryFromGarden(entryId: number): Promise<FetchResult<void>> {
+        let result: FetchResult<void> = {};
+        try {
+            await this.makeFetchWithAuthAndOptions("/garden/remove/" + entryId, {method: "DELETE"});
+        } catch (e) {
+            console.error("An error occurred while removing garden entry with ID", entryId);
+            console.error(e);
+            result = {err: e};
+        }
+        return result;
+    }
+
+    async addToWishlist(plantId: number): Promise<FetchResult<void>> {
+        let result: FetchResult<void> = {};
+        try {
+            await this.makeFetchWithAuthAndOptions("/wishlist/add/" + plantId, {method: "POST"});
+        } catch (e) {
+            console.error("An error occurred while adding plant to wishlist with ID", plantId);
+            console.error(e);
+            result = {err: e};
+        }
+        return result;
+    }
+
+    async clearWishlist(): Promise<FetchResult<number>> {
+        let result: FetchResult<number>;
+        try {
+            const res = await this.makeFetchWithAuthAndOptions("/wishlist/remove/all", {method: "DELETE"});
+            const num = await res.json();
+            result = {value: num}
+        } catch (e) {
+            console.error("An error occurred while clearing wishlist");
+            console.error(e);
+            result = {err: e};
+        }
+        return result;
+    }
+
+    async getWishlistEntries(sort?: string): Promise<FetchResult<Plant[]>> {
+        let result: FetchResult<Plant[]> = {};
+        try {
+            const params = new URLSearchParams();
+            if (sort) params.set("sort", sort);
+            const response = await this.makeFetchWithAuth("/wishlist" + params);
+            const json = await response.json();
+            result = this.parsePlants(json);
+        } catch (e) {
+            console.error("An error occurred while getting wishlist entries")
+            console.error(e);
+            result = {...result, err: e};
+        }
+        return result;
+    }
+
+    async getWishlistSize(): Promise<FetchResult<number>> {
+        let result: FetchResult<number> = {};
+        try {
+            const response = await this.makeFetchWithAuth("/wishlist/count");
+            const json = await response.json();
+            const size = Number.parseInt(json);
+            result = {value: size};
+        } catch (e) {
+            console.error("An error occurred while fetching wishlist size")
+            console.error(e);
+            result = {...result, err: e};
+        }
+        return result;
+    }
+
+    async removeFromWishlist(entryId: number): Promise<FetchResult<void>> {
+        let result: FetchResult<void> = {};
+        try {
+            await this.makeFetchWithAuthAndOptions("/wishlist/remove/" + entryId, {method: "DELETE"});
+        } catch (e) {
+            console.error("An error occurred while removing entry from wishlist with id", entryId)
+            console.error(e);
+            result = {err: e};
+        }
+        return result;
+    }
+
+    private makeFetchWithAuth(path: string): Promise<Response> {
+        return this.makeFetchWithAuthAndOptions(path, {});
+    }
+
+    private makeFetchWithAuthAndOptions(path: string, options: {
+        method?: HttpMethod,
+        body?: object
+    }): Promise<Response> {
+        //TODO: get auth
+        console.log("Making request to", path)
+        const {method, body} = options;
+        const jwt: string = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJsdWthcy5rYXJzY2hAZ214LmRlIiwiaWF0IjoxNzAzNTA5MDUwLCJleHAiOjE3MDM1OTU0NTB9.YF7aFsv2okyXWiytpZIFfqVQ9Y76NBmRg32Hbl4q6Yo";
+        let headers: HeadersInit = {
+            Authorization: `Bearer ${jwt}`
+        };
+        if (body) {
+            headers = {...headers, contentType: "application/json"}
+        }
+        return fetch(this.baseUrl + path, {
+            method: method,
+            headers: headers,
+            body: JSON.stringify(body),
+        });
+    }
+
+    private parseSinglePlant(json: any): FetchResult<Plant> {
+        let result: FetchResult<Plant> = {};
+        try {
+            result = {value: PlantSchema.parse(json)};
+        } catch (e) {
+            if (e instanceof ZodError) {
+                result = {...result, err: "One or more plants could not be parsed correctly."}
+            }
+        }
+        return result;
+    }
+
+    private parsePlants(json: any): FetchResult<Plant[]> {
+        let result: FetchResult<Plant[]> = {};
+        const plants: Plant[] = [];
+        for (const p of json) {
+            try {
+                plants.push(PlantSchema.parse(p))
+            } catch (e) {
+                if (e instanceof ZodError) {
+                    result = {...result, err: "One or more plants could not be parsed correctly."}
+                }
+            }
+        }
+        return {...result, value: plants};
+    }
+
+    private parsePlantsFromPage(json: any): FetchResult<CustomPlantPage> {
+        let result: FetchResult<CustomPlantPage> = {};
+        try {
+            result = {value: CustomPlantPageSchema.parse(json)}
+        } catch (e) {
+            if (e instanceof ZodError) {
+                result = {...result, err: "One or more plants could not be parsed correctly."}
+            }
+        }
+        return result;
+    }
+}
diff --git a/growbros-frontend/src/utils/FetchResult.ts b/growbros-frontend/src/utils/FetchResult.ts
new file mode 100644
index 0000000000000000000000000000000000000000..aa4b74838e7738631638993f1b2ad390ae04d4c6
--- /dev/null
+++ b/growbros-frontend/src/utils/FetchResult.ts
@@ -0,0 +1,4 @@
+export type FetchResult<T> = {
+    value?: T;
+    err?: unknown
+}
\ No newline at end of file
diff --git a/growbros-frontend/src/utils/IBackendConnector.ts b/growbros-frontend/src/utils/IBackendConnector.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0ed10025e4bdc6b4ce7a4598d7d19436e290c574
--- /dev/null
+++ b/growbros-frontend/src/utils/IBackendConnector.ts
@@ -0,0 +1,32 @@
+import {CustomPlantPage, Plant, SearchRequest} from "./schemas.ts";
+import {FetchResult} from "./FetchResult.ts";
+
+export interface IBackendConnector {
+    getAllPlants(page?: number, pageSize?: number): Promise<FetchResult<CustomPlantPage>>;
+
+    searchPlants(search: SearchRequest): Promise<FetchResult<Plant[]>>;
+
+    getRandomPlants(amount: number): Promise<FetchResult<Plant[]>>;
+
+    getSinglePlant(id: number): Promise<FetchResult<Plant | null>>;
+
+    addToGarden(plantId: number): Promise<FetchResult<void>>;
+
+    getGardenEntries(sort?: string): Promise<FetchResult<Plant[]>>;
+
+    getGardenSize(): Promise<FetchResult<number>>;
+
+    removeEntryFromGarden(entryId: number): Promise<FetchResult<void>>;
+
+    clearGarden(): Promise<FetchResult<number>>;
+
+    addToWishlist(plantId: number): Promise<FetchResult<void>>;
+
+    getWishlistEntries(sort?: string): Promise<FetchResult<Plant[]>>
+
+    getWishlistSize(): Promise<FetchResult<number>>;
+
+    removeFromWishlist(entryId: number): Promise<FetchResult<void>>
+
+    clearWishlist(): Promise<FetchResult<number>>;
+}
\ No newline at end of file
diff --git a/growbros-frontend/src/utils/commonTypes.d.ts b/growbros-frontend/src/utils/commonTypes.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..db207868945c8abb3552bb62e980e993769e7d42
--- /dev/null
+++ b/growbros-frontend/src/utils/commonTypes.d.ts
@@ -0,0 +1,13 @@
+export type propsDropDownFilter = {
+    options: Array<string>;
+    topic: string;
+};
+
+
+export type propsSliderFilter = {
+    topic: string;
+    min: number;
+    max: number;
+};
+
+export type HttpMethod = "GET" | "POST" | "DELETE" | "PUT" | "PATCH";
diff --git a/growbros-frontend/src/utils/schemas.ts b/growbros-frontend/src/utils/schemas.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2607128569de1c2ef92ea38613a883073cd7b61d
--- /dev/null
+++ b/growbros-frontend/src/utils/schemas.ts
@@ -0,0 +1,88 @@
+import z from "zod"
+
+const groundType=z.enum(["HEAVY", "MEDIUM", "LIGHT"])
+const waterDemand=z.enum(["DRY","WET","VERY_WET"])
+const lightingDemand=z.enum(["LOW","MEDIUM","HIGH"])
+const nutrientDemand=z.enum(["LOW","MEDIUM","HIGH"])
+const weekNumber= z.number().int().min(0).max(51)
+
+export const PlantSchema = z.object({
+    id: z.number(),
+    name: z.string(),
+    latinName: z.string().nullable(),
+    description: z.string().nullable(),
+    origin: z.string().nullable(),
+    growingTips: z.string().nullable(),
+    plantWeekStart: z.number().int().gte(0).nullable(),
+    plantWeekEnd: z.number().int().gte(0).nullable(),
+    harvestWeekStart: z.number().int().gte(0).nullable(),
+    harvestWeekEnd: z.number().int().gte(0).nullable(),
+    groundType: groundType.transform(s => translateGroundType(s)).nullable(),
+    waterDemand: waterDemand.transform(s=>translateWaterDemand(s)).nullable(),
+    lightingDemand: lightingDemand.transform(s=>translateLightingDemand(s)).nullable(),
+    nutrientDemand: nutrientDemand.transform(s=>translateNutrientDemand(s)).nullable(),
+    imageUrl: z.string().optional()
+  });
+  
+  export type Plant = z.infer<typeof PlantSchema>;
+
+  function translateLightingDemand(key: "LOW"|"MEDIUM"|"HIGH"){
+    const map = {
+        LOW: "Niedrig",
+        MEDIUM: "Mittel",
+        HIGH: "Hoch"
+    } 
+    return map[key];
+  }
+
+  function translateGroundType(key: "HEAVY" | "MEDIUM" | "LIGHT") {
+    const map = {
+        HEAVY: "Schwer",
+        MEDIUM: "Mittel",
+        LIGHT: "Leicht"
+    } 
+    return map[key];
+  }
+
+  function translateWaterDemand(key: "DRY"|"WET"|"VERY_WET"){
+    const map = {
+        DRY: "Trocken",
+        WET: "Feucht",
+        VERY_WET: "Sehr feucht"
+    } 
+    return map[key];
+  }
+
+  function translateNutrientDemand(key: "LOW"|"MEDIUM"|"HIGH"){
+    const map = {
+        LOW: "Nierig",
+        MEDIUM: "Mittel",
+        HIGH: "Hoch"
+    } 
+    return map[key];
+  }
+
+export const SearchRequestSchema = z.object({
+    searchTerm: z.string().optional(),
+    waterDemand: waterDemand.optional(),
+    nutrientDemand: nutrientDemand.optional(),
+    groundType: groundType.optional(),
+    lightingDemand: lightingDemand.optional(),
+    plantWeekStart: weekNumber.optional(),
+    plantWeekEnd: weekNumber.optional(),
+    growthDurationMin: weekNumber.optional(),
+    growthDurationMax: weekNumber.optional()
+  })
+
+export type SearchRequest = z.infer<typeof SearchRequestSchema>;
+
+function createCustomPageSchema<ItemType extends z.ZodTypeAny>(item: ItemType) {
+    return z.object({
+        currentPage: z.number().int(),
+        pageSize: z.number().int(),
+        content: z.array(item)
+    });
+}
+
+export const CustomPlantPageSchema = createCustomPageSchema(PlantSchema);
+export type CustomPlantPage = z.infer<typeof CustomPlantPageSchema>;
diff --git a/growbros-frontend/src/utils/useGrowbrosFetcher.ts b/growbros-frontend/src/utils/useGrowbrosFetcher.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d1819d622972b9a4f71b588cf31cec00d0eec189
--- /dev/null
+++ b/growbros-frontend/src/utils/useGrowbrosFetcher.ts
@@ -0,0 +1,17 @@
+import {IBackendConnector} from "./IBackendConnector.ts";
+import {useMemo} from "react";
+import {BackendConnectorImpl} from "./BackendConnectorImpl.ts";
+
+const createFetcherInstance = (): IBackendConnector => {
+    const backendUrl = import.meta.env.VITE_GROWBROS_BACKEND_URL;
+
+    return new BackendConnectorImpl(backendUrl);
+};
+
+const useGrowbrosFetcher = (): IBackendConnector => {
+    const fetcherInstance = useMemo(() => createFetcherInstance(), []);
+
+    return fetcherInstance;
+};
+
+export default useGrowbrosFetcher;
diff --git a/requests.http b/requests.http
index e985f72afbcf011c9f1d1b621a74ac3f8b1e60ce..eb3f119aaa851a599c4f91479f595df5541487be 100644
--- a/requests.http
+++ b/requests.http
@@ -1,6 +1,6 @@
 ### Get all plants
 GET http://localhost:8080/api/v1/plants
-Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJsdWthcy5rYXJzY2hAZ214LmRlIiwiaWF0IjoxNzAwOTMzNjQ4LCJleHAiOjE3MDEwMjAwNDh9.IXoMuNecB7ARvZpEyx5SraMbdoZrHgADeHd7wAo0ddw
+Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJsdWthcy5rYXJzY2hAZ214LmRlIiwiaWF0IjoxNzAzMjYwNDU5LCJleHAiOjE3MDMzNDY4NTl9.Crt0lc8CgpQAQdi_--9CLZxpaLcb_1IM22-aRAbbMuU
 
 ### Get garden entries
 GET http://localhost:8080/api/v1/garden
diff --git a/src/main/java/hdm/mi/growbros/controllers/PlantsController.java b/src/main/java/hdm/mi/growbros/controllers/PlantsController.java
index 9c751ce26ce94ca58870ec263f953519f0f7724e..7e90c181fcf4583175b31098255d40d8397bd436 100644
--- a/src/main/java/hdm/mi/growbros/controllers/PlantsController.java
+++ b/src/main/java/hdm/mi/growbros/controllers/PlantsController.java
@@ -1,5 +1,6 @@
 package hdm.mi.growbros.controllers;
 
+import hdm.mi.growbros.exceptions.PlantNotFoundException;
 import hdm.mi.growbros.models.dto.CustomPageDto;
 import hdm.mi.growbros.models.plant.Plant;
 import hdm.mi.growbros.models.search.SearchRequest;
@@ -12,12 +13,12 @@ import java.util.Collection;
 
 @RestController
 @CrossOrigin
-@RequestMapping("/api/v1")
+@RequestMapping("/api/v1/plants")
 @RequiredArgsConstructor
 public class PlantsController {
     private final PlantsService plantsService;
 
-    @GetMapping("/plants")
+    @GetMapping
     public CustomPageDto<Plant> getAllPlants(
             @RequestParam(value = "page", defaultValue = "0") int page,
             @RequestParam(value = "pageSize", defaultValue = "25") int pageSize
@@ -25,17 +26,22 @@ public class PlantsController {
         return plantsService.getPlants(page, pageSize);
     }
 
-    @GetMapping("/plants/randomPlants/{numberOfPlants}")
+    @GetMapping("/{id}")
+    public Plant getPlant(@PathVariable long id) {
+        return plantsService.findById(id).orElseThrow(() -> new PlantNotFoundException(id));
+    }
+
+    @GetMapping("/randomPlants/{numberOfPlants}")
     public Collection<Plant> getRandomPlants(@PathVariable Integer numberOfPlants) {
         return plantsService.getRandomPlants(numberOfPlants);
     }
 
-    @GetMapping("/plants/search")
-    public Collection<Plant> getPlantsSearchedFor(@RequestBody @Valid SearchRequest searchRequest) {
+    @GetMapping("/search")
+    public Collection<Plant> getPlantsSearchedFor(@Valid SearchRequest searchRequest) {
         return plantsService.getPlantsSearchedFor(searchRequest);
     }
 
-    @PostMapping("/plants")
+    @PostMapping
     public void createPlant(@RequestBody @Valid Plant plant) {
         plantsService.createPlant(plant);
     }
diff --git a/src/main/java/hdm/mi/growbros/models/plant/GroundType.java b/src/main/java/hdm/mi/growbros/models/plant/GroundType.java
index 7228f1304991126a2f00d40de8dc3f118a8c04fe..9e05ddc9044ffce86ddcdbac9b48e9b58a025d6c 100644
--- a/src/main/java/hdm/mi/growbros/models/plant/GroundType.java
+++ b/src/main/java/hdm/mi/growbros/models/plant/GroundType.java
@@ -6,9 +6,9 @@ import lombok.RequiredArgsConstructor;
 @Getter
 @RequiredArgsConstructor
 public enum GroundType {
-    LIGHT("Light"),
-    MEDIUM("Medium"),
-    HEAVY("Heavy");
+    LIGHT("Leicht"),
+    MEDIUM("Mittel"),
+    HEAVY("Schwer");
 
     private final String name;
 }
diff --git a/src/main/java/hdm/mi/growbros/security/SecurityConfiguration.java b/src/main/java/hdm/mi/growbros/security/SecurityConfiguration.java
index fda8d6bf17f8558d2bc8779f4f386b32df8368cb..9746f8c17221e51f80823d90abad1ce78c6b25e1 100644
--- a/src/main/java/hdm/mi/growbros/security/SecurityConfiguration.java
+++ b/src/main/java/hdm/mi/growbros/security/SecurityConfiguration.java
@@ -11,11 +11,14 @@ import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.web.SecurityFilterChain;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
 import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
 import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
 
-import static hdm.mi.growbros.models.user.Role.ADMIN;
+import java.util.List;
+
 import static org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console;
-import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasRole;
 
 /**
  * Configuration of the filter chain.
@@ -30,6 +33,7 @@ public class SecurityConfiguration {
     @Bean
     public SecurityFilterChain securityFilterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
         http
+                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                 .csrf(csrf -> {
                     csrf.disable(); //CSRF-Schutz deaktivieren
                     csrf.ignoringRequestMatchers(toH2Console());
@@ -56,14 +60,21 @@ public class SecurityConfiguration {
     }
 
     @Bean
-    MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
+    public MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
         //see https://stackoverflow.com/questions/76809698/spring-security-method-cannot-decide-pattern-is-mvc-or-not-spring-boot-applicati
         return new MvcRequestMatcher.Builder(introspector);
     }
 
-    /*@Bean
-    protected void configure(HttpSecurity http) throws Exception {
-        http.authorizeRequests().requestMatchers("/swagger-ui.html")
-                .access("hasRole('ROLE_ADMIN')");
-    }*/
+    @Bean
+    public CorsConfigurationSource corsConfigurationSource() {
+        CorsConfiguration corsConfiguration = new CorsConfiguration();
+        corsConfiguration.setAllowedOrigins(List.of("*"));
+        corsConfiguration.setAllowedMethods(List.of("*"));
+        //corsConfiguration.setAllowCredentials(true);
+        corsConfiguration.setAllowedHeaders(List.of("*"));
+        corsConfiguration.setMaxAge(3600L);
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", corsConfiguration);
+        return source;
+    }
 }
diff --git a/src/main/java/hdm/mi/growbros/service/GardenService.java b/src/main/java/hdm/mi/growbros/service/GardenService.java
index e64aeacd20c2f7a885787789468a955e32499b26..b52e8c967223544b67303d86b3169a564458971f 100644
--- a/src/main/java/hdm/mi/growbros/service/GardenService.java
+++ b/src/main/java/hdm/mi/growbros/service/GardenService.java
@@ -7,6 +7,7 @@ import hdm.mi.growbros.models.user.User;
 import hdm.mi.growbros.repositories.GardenRepository;
 import hdm.mi.growbros.repositories.PlantRepository;
 import hdm.mi.growbros.util.DateTimeUtils;
+import jakarta.transaction.Transactional;
 import lombok.RequiredArgsConstructor;
 import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
@@ -40,10 +41,12 @@ public class GardenService {
         return result.getPlant();
     }
 
+    @Transactional
     public void removeFromGarden(Long entryId, User authenticatedUser) {
         gardenRepository.deleteByIdAndUser(entryId, authenticatedUser);
     }
 
+    @Transactional
     public int clearGarden(User authenticatedUser) {
         return gardenRepository.deleteAllByUser(authenticatedUser);
     }
diff --git a/src/main/java/hdm/mi/growbros/service/PlantsService.java b/src/main/java/hdm/mi/growbros/service/PlantsService.java
index 41ac6c79fa8b33bfd4326e3d8f239a4ef64f7750..1d6c0fda032984276520e838e944438d89948761 100644
--- a/src/main/java/hdm/mi/growbros/service/PlantsService.java
+++ b/src/main/java/hdm/mi/growbros/service/PlantsService.java
@@ -3,8 +3,8 @@ package hdm.mi.growbros.service;
 import hdm.mi.growbros.models.dto.CustomPageDto;
 import hdm.mi.growbros.models.plant.Plant;
 import hdm.mi.growbros.models.search.PlantSpecification;
-import hdm.mi.growbros.repositories.PlantRepository;
 import hdm.mi.growbros.models.search.SearchRequest;
+import hdm.mi.growbros.repositories.PlantRepository;
 import lombok.RequiredArgsConstructor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,4 +55,8 @@ public class PlantsService {
         log.info("Saving plant '{}' to repository.", plant.getName());
         plantRepository.save(plant);
     }
+
+    public Optional<Plant> findById(long id) {
+        return plantRepository.findById(id);
+    }
 }
diff --git a/src/main/java/hdm/mi/growbros/service/WishListService.java b/src/main/java/hdm/mi/growbros/service/WishListService.java
index 0d832d672cd617de3053b346178779ed0c847c68..d5a869be79bb105e58c2034e8ea43d93c543f59a 100644
--- a/src/main/java/hdm/mi/growbros/service/WishListService.java
+++ b/src/main/java/hdm/mi/growbros/service/WishListService.java
@@ -7,6 +7,7 @@ import hdm.mi.growbros.models.user.User;
 import hdm.mi.growbros.repositories.PlantRepository;
 import hdm.mi.growbros.repositories.WishListRepository;
 import hdm.mi.growbros.util.DateTimeUtils;
+import jakarta.transaction.Transactional;
 import lombok.RequiredArgsConstructor;
 import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
@@ -45,10 +46,12 @@ public class WishListService {
         wishListRepository.save(wishListEntry);
     }
 
+    @Transactional
     public void removeFromWishList(Long entryId, User user) {
         wishListRepository.deleteByIdAndUser(entryId, user);
     }
 
+    @Transactional
     public int clearWishList(User user) {
         return wishListRepository.deleteAllByUser(user);
     }