{"id":38619,"date":"2026-02-04T08:40:55","date_gmt":"2026-02-04T05:40:55","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=38619"},"modified":"2026-02-04T08:40:55","modified_gmt":"2026-02-04T05:40:55","slug":"react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/","title":{"rendered":"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?"},"content":{"rendered":"<p><body><\/p>\n<h2>React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?<\/h2>\n<h2>Giri\u015f<\/h2>\n<p>G\u00fcn\u00fcm\u00fcz\u00fcn h\u0131zla de\u011fi\u015fen dijital d\u00fcnyas\u0131nda, kullan\u0131c\u0131 deneyimini merkeze alan, performansl\u0131 ve \u00f6l\u00e7eklenebilir uygulamalar geli\u015ftirmek b\u00fcy\u00fck \u00f6nem ta\u015f\u0131maktad\u0131r. Bu makalede, modern web geli\u015ftirmenin en g\u00fc\u00e7l\u00fc ara\u00e7lar\u0131ndan baz\u0131lar\u0131n\u0131 bir araya getirerek dinamik bir yemek tarifi uygulamas\u0131 olu\u015fturma s\u00fcrecini ad\u0131m ad\u0131m inceleyece\u011fiz: React ile zengin bir kullan\u0131c\u0131 aray\u00fcz\u00fc, GraphQL ile esnek ve verimli bir API katman\u0131 ve Prisma ile g\u00fc\u00e7l\u00fc, tip g\u00fcvenli bir veritaban\u0131 etkile\u015fimi sa\u011flayaca\u011f\u0131z.<\/p>\n<p>Yemek tarifi uygulamalar\u0131, genellikle karma\u015f\u0131k veri yap\u0131lar\u0131na (tarifler, malzemeler, ad\u0131mlar, kategoriler, kullan\u0131c\u0131 yorumlar\u0131 vb.) ve \u00e7e\u015fitli kullan\u0131c\u0131 etkile\u015fimlerine (tarif arama, filtreleme, ekleme, d\u00fczenleme, favorilere ekleme) sahip olduklar\u0131 i\u00e7in, bu teknolojilerin g\u00fcc\u00fcn\u00fc sergilemek i\u00e7in m\u00fckemmel birer \u00f6rnek te\u015fkil eder. Bu teknoloji y\u0131\u011f\u0131n\u0131, geli\u015ftiricilere hem frontend hem de backend taraf\u0131nda \u00fcst d\u00fczey bir verimlilik ve esneklik sunar.<\/p>\n<p>Bu makalenin amac\u0131, ba\u015flang\u0131\u00e7 seviyesinden ileri seviyeye kadar t\u00fcm geli\u015ftiricilere hitap eden kapsaml\u0131 bir rehber sunmakt\u0131r. Proje kurulumundan veritaban\u0131 modellemeye, GraphQL sunucusu olu\u015fturmaktan React bile\u015fenlerini entegre etmeye kadar her ad\u0131m\u0131 detayl\u0131ca ele alaca\u011f\u0131z. Ayr\u0131ca, kimlik do\u011frulama, hata y\u00f6netimi ve da\u011f\u0131t\u0131m gibi geli\u015fmi\u015f konulara da de\u011finerek uygulaman\u0131z\u0131 \u00fcretime haz\u0131r hale getirme konusunda size yol g\u00f6sterece\u011fiz.<\/p>\n<h2>Teknoloji Se\u00e7imleri ve Nedenleri<\/h2>\n<p>Bu projede kulland\u0131\u011f\u0131m\u0131z her bir teknoloji, belirli bir problemi \u00e7\u00f6zmek ve geli\u015ftirme s\u00fcrecini optimize etmek i\u00e7in \u00f6zenle se\u00e7ilmi\u015ftir. \u0130\u015fte bu teknolojilerin tercih edilme nedenleri:<\/p>\n<h3>React (Frontend)<\/h3>\n<p>React, Facebook taraf\u0131ndan geli\u015ftirilen ve kullan\u0131c\u0131 aray\u00fczleri olu\u015fturmak i\u00e7in kullan\u0131lan pop\u00fcler bir JavaScript k\u00fct\u00fcphanesidir. Bile\u015fen tabanl\u0131 mimarisi sayesinde, uygulaman\u0131n farkl\u0131 b\u00f6l\u00fcmlerini ba\u011f\u0131ms\u0131z, yeniden kullan\u0131labilir par\u00e7alara ay\u0131rmak m\u00fcmk\u00fcnd\u00fcr. Bu, kodun daha d\u00fczenli, bak\u0131m\u0131 daha kolay ve geli\u015ftirme s\u00fcrecinin daha h\u0131zl\u0131 olmas\u0131n\u0131 sa\u011flar. Sanal DOM (Virtual DOM) kullan\u0131m\u0131 sayesinde, DOM g\u00fcncellemeleri optimize edilir ve bu da y\u00fcksek performansl\u0131 kullan\u0131c\u0131 aray\u00fczleri sunar. Geni\u015f bir geli\u015ftirici toplulu\u011fu ve zengin bir ekosisteme sahip olmas\u0131, kar\u015f\u0131la\u015f\u0131lan sorunlara h\u0131zl\u0131 \u00e7\u00f6z\u00fcmler bulunmas\u0131n\u0131 ve haz\u0131r k\u00fct\u00fcphanelerden faydalan\u0131lmas\u0131n\u0131 kolayla\u015ft\u0131r\u0131r. Yemek tarifi uygulamam\u0131zda, tarif listelerini, detay sayfalar\u0131n\u0131, formlar\u0131 ve di\u011fer etkile\u015fimli elemanlar\u0131 olu\u015fturmak i\u00e7in React&#8217;\u0131n g\u00fcc\u00fcnden faydalanaca\u011f\u0131z.<\/p>\n<h3>GraphQL (API Katman\u0131)<\/h3>\n<p>GraphQL, API&#8217;ler i\u00e7in bir sorgu dili ve \u00e7al\u0131\u015fma zaman\u0131d\u0131r. RESTful API&#8217;lere k\u0131yasla bir\u00e7ok avantaj sunar. En b\u00fcy\u00fck avantajlar\u0131ndan biri, istemcinin tam olarak ihtiyac\u0131 olan veriyi talep etmesine olanak tan\u0131mas\u0131d\u0131r. Bu, &#8220;over-fetching&#8221; (gere\u011finden fazla veri \u00e7ekme) ve &#8220;under-fetching&#8221; (gereken t\u00fcm veriyi tek seferde alamama) sorunlar\u0131n\u0131 ortadan kald\u0131r\u0131r. Tek bir endpoint \u00fczerinden t\u00fcm veri i\u015flemlerini y\u00f6netebilir, b\u00f6ylece API geli\u015ftirme ve bak\u0131m\u0131n\u0131 basitle\u015ftirebilirsiniz. G\u00fc\u00e7l\u00fc tip sistemi sayesinde, API&#8217;nizin ne t\u00fcr veriler d\u00f6nd\u00fcrece\u011fi ve ne t\u00fcr arg\u00fcmanlar kabul edece\u011fi a\u00e7\u0131k\u00e7a tan\u0131mlan\u0131r; bu da istemci ve sunucu aras\u0131ndaki ileti\u015fimi daha g\u00fcvenilir hale getirir. GraphiQL gibi ara\u00e7lar, API&#8217;yi ke\u015ffetmeyi ve test etmeyi son derece kolayla\u015ft\u0131r\u0131r. Yemek tarifi uygulamam\u0131zda, tarifleri sorgulamak, yeni tarifler eklemek, mevcut tarifleri g\u00fcncellemek veya silmek i\u00e7in GraphQL&#8217;i kullanaca\u011f\u0131z.<\/p>\n<h3>Prisma (ORM\/Veritaban\u0131 Katman\u0131)<\/h3>\n<p>Prisma, modern bir veritaban\u0131 ara\u00e7 tak\u0131m\u0131d\u0131r ve \u00f6zellikle TypeScript ile m\u00fckemmel bir uyum i\u00e7indedir. Bir Object-Relational Mapper (ORM) olarak, veritaban\u0131 i\u015flemlerini JavaScript\/TypeScript kodunuzla yapman\u0131z\u0131 sa\u011flar, SQL sorgular\u0131 yazma ihtiyac\u0131n\u0131 ortadan kald\u0131r\u0131r. Prisma&#8217;n\u0131n en g\u00fc\u00e7l\u00fc \u00f6zelliklerinden biri, <code>schema.prisma<\/code> dosyas\u0131 arac\u0131l\u0131\u011f\u0131yla veritaban\u0131 \u015feman\u0131z\u0131 kod olarak tan\u0131mlayabilmenizdir (Schema-as-Code). Bu, veritaban\u0131 \u015feman\u0131z\u0131n versiyon kontrol\u00fcn\u00fc yapman\u0131za ve <code>prisma migrate<\/code> komutlar\u0131yla kolayca de\u011fi\u015fiklikleri uygulaman\u0131za olanak tan\u0131r. Tip g\u00fcvenli\u011fi, otomatik tamamlama ve derleme zaman\u0131 kontrolleri sayesinde geli\u015ftirici deneyimini \u00f6nemli \u00f6l\u00e7\u00fcde art\u0131r\u0131r ve hatalar\u0131 azalt\u0131r. PostgreSQL, MySQL, SQLite, SQL Server ve MongoDB gibi \u00e7e\u015fitli veritabanlar\u0131n\u0131 destekler. Yemek tarifi uygulamam\u0131zda, tarifler ve malzemeler gibi modelleri tan\u0131mlamak, bu modeller \u00fczerinde CRUD (Olu\u015fturma, Okuma, G\u00fcncelleme, Silme) i\u015flemleri yapmak ve veritaban\u0131 ile etkile\u015fim kurmak i\u00e7in Prisma&#8217;y\u0131 kullanaca\u011f\u0131z.<\/p>\n<h2>Proje Kurulumu ve Temel Yap\u0131land\u0131rma<\/h2>\n<p>Uygulamam\u0131z\u0131 geli\u015ftirmeye ba\u015flamadan \u00f6nce, frontend ve backend i\u00e7in ayr\u0131 ayr\u0131 projeler olu\u015fturup temel yap\u0131land\u0131rmalar\u0131 yapmam\u0131z gerekiyor.<\/p>\n<h3>Proje Ba\u015flatma (Frontend)<\/h3>\n<p>React uygulamas\u0131n\u0131 ba\u015flatmak i\u00e7in Vite veya Create React App kullanabiliriz. Vite, daha h\u0131zl\u0131 bir geli\u015ftirme deneyimi sunar, bu y\u00fczden onu tercih edece\u011fiz:<\/p>\n<pre><code class=\"language-bash\"># Frontend projesi olu\u015fturma\nnpm create vite@latest recipe-app-frontend -- --template react-ts\ncd recipe-app-frontend\nnpm install\nnpm run dev<\/code><\/pre>\n<p>Bu komutlar, <code>recipe-app-frontend<\/code> ad\u0131nda bir dizin olu\u015fturacak, temel React projesini kuracak ve geli\u015ftirme sunucusunu ba\u015flatacakt\u0131r.<\/p>\n<h3>Backend Kurulumu (GraphQL Sunucusu ve Prisma)<\/h3>\n<p>Backend projemizi ayr\u0131 bir dizinde olu\u015fturaca\u011f\u0131z. Bu dizin, GraphQL sunucumuzu ve Prisma konfig\u00fcrasyonlar\u0131m\u0131z\u0131 i\u00e7erecek.<\/p>\n<pre><code class=\"language-bash\"># Backend projesi olu\u015fturma\nmkdir recipe-app-backend\ncd recipe-app-backend\nnpm init -y\n\n<h2>Gerekli paketleri y\u00fckleme<\/h2>\nnpm install express apollo-server-express graphql prisma @prisma\/client typescript ts-node nodemon dotenv\nnpm install --save-dev @types\/express @types\/graphql @types\/node\n\n<h2>TypeScript yap\u0131land\u0131rmas\u0131<\/h2>\nnpx tsc --init<\/code><\/pre>\n<p><code>tsconfig.json<\/code> dosyas\u0131n\u0131 d\u00fczenleyerek <code>outDir<\/code> ve <code>rootDir<\/code> gibi ayarlar\u0131 yapabilirsiniz. \u00d6rne\u011fin:<\/p>\n<pre><code class=\"language-json\">\/\/ tsconfig.json\n{\n  \"compilerOptions\": {\n    \"target\": \"es2016\",\n    \"module\": \"commonjs\",\n    \"outDir\": \".\/dist\",\n    \"rootDir\": \".\/src\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true,\n    \"forceConsistentCasingInFileNames\": true\n  },\n  \"include\": [\"src\/<em><\/em>\/*.ts\"],\n  \"exclude\": [\"node_modules\"]\n}<\/code><\/pre>\n<p>\u015eimdi Prisma&#8217;y\u0131 projemize dahil edelim:<\/p>\n<pre><code class=\"language-bash\">npx prisma init --datasource-provider postgresql<\/code><\/pre>\n<p>Bu komut, <code>prisma<\/code> dizini i\u00e7inde <code>schema.prisma<\/code> dosyas\u0131n\u0131 ve <code>.env<\/code> dosyas\u0131n\u0131 olu\u015fturacakt\u0131r. <code>.env<\/code> dosyas\u0131na veritaban\u0131 ba\u011flant\u0131 URL&#8217;nizi eklemeniz gerekmektedir. \u00d6rne\u011fin:<\/p>\n<pre><code class=\"language-\"># .env\nDATABASE_URL=\"postgresql:\/\/user:password@localhost:5432\/recipe_db?schema=public\"<\/code><\/pre>\n<p>Veritaban\u0131 URL&#8217;nizi kendi veritaban\u0131 bilgilerinize g\u00f6re de\u011fi\u015ftirmeyi unutmay\u0131n. Yerel bir PostgreSQL veritaban\u0131 kullanabilir veya Render, Supabase gibi bulut servislerinden faydalanabilirsiniz.<\/p>\n<h3>Veritaban\u0131 \u015eemas\u0131 Tan\u0131mlama (Prisma Schema)<\/h3>\n<p><code>prisma\/schema.prisma<\/code> dosyas\u0131n\u0131 a\u00e7arak yemek tarifi uygulamam\u0131z i\u00e7in temel modelleri tan\u0131mlayaca\u011f\u0131z. <code>Recipe<\/code> (Tarif) ve <code>Ingredient<\/code> (Malzeme) modelleri, bu uygulaman\u0131n \u00e7ekirde\u011fini olu\u015fturacakt\u0131r.<\/p>\n<pre><code class=\"language-prisma\">\/\/ prisma\/schema.prisma\ngenerator client {\n  provider = \"prisma-client-js\"\n}\n\ndatasource db {\n  provider = \"postgresql\"\n  url      = env(\"DATABASE_URL\")\n}\n\nmodel Recipe {\n  id          String      @id @default(uuid())\n  title       String      @unique\n  description String?\n  instructions String\n  prepTime    Int?\n  cookTime    Int?\n  servings    Int?\n  category    String?\n  imageUrl    String?\n  createdAt   DateTime    @default(now())\n  updatedAt   DateTime    @updatedAt\n  ingredients Ingredient[] \/\/ Bir tarifin birden fazla malzemesi olabilir\n}\n\nmodel Ingredient {\n  id       String  @id @default(uuid())\n  name     String\n  quantity String? \/\/ \u00d6rne\u011fin: \"2 su barda\u011f\u0131\", \"yar\u0131m \u00e7ay ka\u015f\u0131\u011f\u0131\"\n  recipeId String\n  recipe   Recipe  @relation(fields: [recipeId], references: [id])\n}<\/code><\/pre>\n<p>Burada <code>Recipe<\/code> modeli, bir yeme\u011fin temel bilgilerini i\u00e7erirken, <code>Ingredient<\/code> modeli ise o yeme\u011fin malzemelerini tutar. <code>Recipe<\/code> ve <code>Ingredient<\/code> aras\u0131nda bire \u00e7ok (one-to-many) bir ili\u015fki tan\u0131mlad\u0131k: bir tarifin birden fazla malzemesi olabilir, ancak bir malzeme yaln\u0131zca tek bir tarife aittir. <code>id<\/code> alanlar\u0131 i\u00e7in <code>uuid()<\/code> kullanmak, benzersiz ve tahmin edilemez kimlikler sa\u011flar.<\/p>\n<h3>Veritaban\u0131 Migrasyonlar\u0131<\/h3>\n<p>\u015eema tan\u0131mlad\u0131ktan sonra, bu \u015femay\u0131 veritaban\u0131m\u0131za uygulamam\u0131z gerekiyor. Prisma&#8217;n\u0131n migration arac\u0131 bu konuda bize yard\u0131mc\u0131 olur:<\/p>\n<pre><code class=\"language-bash\">npx prisma migrate dev --name init<\/code><\/pre>\n<p>Bu komut, Prisma \u015femas\u0131na g\u00f6re veritaban\u0131n\u0131zda tablolar\u0131 olu\u015fturacak ve <code>prisma\/migrations<\/code> dizini alt\u0131na bir migration dosyas\u0131 ekleyecektir. \u0130lk migration&#8217;\u0131m\u0131z genellikle <code>init<\/code> olarak adland\u0131r\u0131l\u0131r.<\/p>\n<h2>GraphQL Sunucusu Olu\u015fturma<\/h2>\n<p>Backend projemizin <code>src<\/code> dizini alt\u0131nda GraphQL sunucumuzu kuraca\u011f\u0131z. <code>src\/index.ts<\/code> ana dosyam\u0131z olacak.<\/p>\n<h3>GraphQL \u015eemas\u0131 Tan\u0131mlama (Type Definitions)<\/h3>\n<p>GraphQL \u015femas\u0131, API&#8217;mizin d\u0131\u015f d\u00fcnyaya hangi veri tiplerini ve hangi operasyonlar\u0131 (sorgular ve mutasyonlar) sundu\u011funu tan\u0131mlar. <code>src\/schema.ts<\/code> dosyas\u0131nda bu tan\u0131mlar\u0131 yapaca\u011f\u0131z:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/schema.ts\nimport { gql } from 'apollo-server-express';\n\nexport const typeDefs = gql<code>\n  type Recipe {\n    id: ID!\n    title: String!\n    description: String\n    instructions: String!\n    prepTime: Int\n    cookTime: Int\n    servings: Int\n    category: String\n    imageUrl: String\n    createdAt: String!\n    updatedAt: String!\n    ingredients: [Ingredient!]!\n  }\n\n  type Ingredient {\n    id: ID!\n    name: String!\n    quantity: String\n  }\n\n  input IngredientInput {\n    name: String!\n    quantity: String\n  }\n\n  input CreateRecipeInput {\n    title: String!\n    description: String\n    instructions: String!\n    prepTime: Int\n    cookTime: Int\n    servings: Int\n    category: String\n    imageUrl: String\n    ingredients: [IngredientInput!]!\n  }\n\n  input UpdateRecipeInput {\n    id: ID!\n    title: String\n    description: String\n    instructions: String\n    prepTime: Int\n    cookTime: Int\n    servings: Int\n    category: String\n    imageUrl: String\n    ingredients: [IngredientInput!]\n  }\n\n  type Query {\n    recipes: [Recipe!]!\n    recipe(id: ID!): Recipe\n  }\n\n  type Mutation {\n    createRecipe(input: CreateRecipeInput!): Recipe!\n    updateRecipe(input: UpdateRecipeInput!): Recipe!\n    deleteRecipe(id: ID!): Recipe!\n  }\n<\/code>;<\/code><\/pre>\n<p>Burada <code>Recipe<\/code> ve <code>Ingredient<\/code> tiplerini, Prisma modellerimizle uyumlu olacak \u015fekilde tan\u0131mlad\u0131k. <code>Query<\/code> tipi, veri okuma operasyonlar\u0131n\u0131 (t\u00fcm tarifleri listeleme, tek bir tarifi getirme) i\u00e7erirken, <code>Mutation<\/code> tipi veri yazma operasyonlar\u0131n\u0131 (yeni tarif olu\u015fturma, g\u00fcncelleme, silme) tan\u0131mlar. <code>Input<\/code> tipleri ise mutasyonlara g\u00f6nderilecek verilerin yap\u0131s\u0131n\u0131 belirler.<\/p>\n<h3>\u00c7\u00f6z\u00fcmleyiciler (Resolvers)<\/h3>\n<p>\u00c7\u00f6z\u00fcmleyiciler (Resolvers), GraphQL \u015femas\u0131ndaki her bir alan i\u00e7in ger\u00e7ek veriyi d\u00f6nd\u00fcrmekten sorumlu fonksiyonlard\u0131r. Bu fonksiyonlar, veritaban\u0131 ile etkile\u015fim kurmak i\u00e7in Prisma istemcisini kullan\u0131r. <code>src\/resolvers.ts<\/code> dosyas\u0131nda \u00e7\u00f6z\u00fcmleyicilerimizi tan\u0131mlayal\u0131m:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/resolvers.ts\nimport { PrismaClient } from '@prisma\/client';\n\nconst prisma = new PrismaClient();\n\nexport const resolvers = {\n  Query: {\n    recipes: async () => {\n      return prisma.recipe.findMany({\n        include: {\n          ingredients: true, \/\/ Tariflerle birlikte malzemeleri de getir\n        },\n      });\n    },\n    recipe: async (_parent: any, { id }: { id: string }) => {\n      return prisma.recipe.findUnique({\n        where: { id },\n        include: {\n          ingredients: true,\n        },\n      });\n    },\n  },\n  Mutation: {\n    createRecipe: async (_parent: any, { input }: { input: any }) => {\n      const { ingredients, ...recipeData } = input;\n      return prisma.recipe.create({\n        data: {\n          ...recipeData,\n          ingredients: {\n            create: ingredients, \/\/ \u0130li\u015fkili malzemeleri de olu\u015ftur\n          },\n        },\n        include: {\n          ingredients: true,\n        },\n      });\n    },\n    updateRecipe: async (_parent: any, { input }: { input: any }) => {\n      const { id, ingredients, ...recipeData } = input;\n      \/\/ Mevcut malzemeleri silip yenilerini olu\u015fturmak veya g\u00fcncellemek daha karma\u015f\u0131k olabilir.\n      \/\/ Basitlik ad\u0131na, burada sadece tarifin kendisini g\u00fcncelleyelim.\n      \/\/ Malzemelerin g\u00fcncellenmesi i\u00e7in ayr\u0131 bir mutasyon veya daha detayl\u0131 bir mant\u0131k gerekebilir.\n      return prisma.recipe.update({\n        where: { id },\n        data: recipeData, \/\/ Sadece recipeData'y\u0131 g\u00fcncelliyoruz\n        include: {\n          ingredients: true,\n        },\n      });\n    },\n    deleteRecipe: async (_parent: any, { id }: { id: string }) => {\n      \/\/ \u0130li\u015fkili malzemeleri de silmek i\u00e7in CASCADE delete ayar\u0131 yap\u0131labilir\n      \/\/ veya \u00f6nce malzemeleri manuel olarak silmek gerekebilir.\n      await prisma.ingredient.deleteMany({\n        where: { recipeId: id },\n      });\n      return prisma.recipe.delete({\n        where: { id },\n      });\n    },\n  },\n};<\/code><\/pre>\n<p>\u00c7\u00f6z\u00fcmleyicilerimiz, <code>prisma<\/code> istemcisini kullanarak veritaban\u0131 sorgular\u0131 yapar. <code>findMany<\/code>, <code>findUnique<\/code>, <code>create<\/code>, <code>update<\/code> ve <code>delete<\/code> gibi Prisma y\u00f6ntemleri, veritaban\u0131 i\u015flemlerini kolayca ger\u00e7ekle\u015ftirmemizi sa\u011flar. \u00d6zellikle <code>createRecipe<\/code> mutasyonunda, <code>ingredients<\/code> alan\u0131 i\u00e7in <code>create<\/code> anahtar kelimesini kullanarak, tek bir i\u015flemde hem tarifi hem de ili\u015fkili malzemeleri olu\u015fturabildi\u011fimize dikkat edin.<\/p>\n<h3>Apollo Sunucusunu Ba\u015flatma<\/h3>\n<p>Son olarak, GraphQL \u015femam\u0131z\u0131 ve \u00e7\u00f6z\u00fcmleyicilerimizi bir araya getirerek Apollo Server&#8217;\u0131 ba\u015flataca\u011f\u0131z. <code>src\/index.ts<\/code> dosyam\u0131z \u015f\u00f6yle g\u00f6r\u00fcnecek:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/index.ts\nimport 'dotenv\/config'; \/\/ .env dosyas\u0131n\u0131 y\u00fcklemek i\u00e7in\nimport express from 'express';\nimport { ApolloServer } from 'apollo-server-express';\nimport { typeDefs } from '.\/schema';\nimport { resolvers } from '.\/resolvers';\nimport { PrismaClient } from '@prisma\/client';\n\nconst prisma = new PrismaClient();\n\nasync function startApolloServer() {\n  const app = express();\n\n  const server = new ApolloServer({\n    typeDefs,\n    resolvers,\n    context: ({ req, res }) => ({\n      prisma, \/\/ Prisma istemcisini t\u00fcm \u00e7\u00f6z\u00fcmleyicilere eri\u015filebilir hale getir\n      \/\/ req, res \/\/ \u0130htiya\u00e7 duyulursa HTTP iste\u011fi ve yan\u0131t nesnelerine eri\u015fim\n    }),\n  });\n\n  await server.start();\n  server.applyMiddleware({ app, path: '\/graphql' });\n\n  const PORT = process.env.PORT || 4000;\n\n  app.listen(PORT, () => {\n    console.log(<code>Server ready at http:\/\/localhost:${PORT}\/graphql<\/code>);\n  });\n}\n\nstartApolloServer();<\/code><\/pre>\n<p>Bu kod par\u00e7as\u0131, <code>express<\/code> ile bir HTTP sunucusu olu\u015fturur, <code>ApolloServer<\/code>&#8216;\u0131 ba\u015flat\u0131r ve GraphQL endpoint&#8217;ini <code>\/graphql<\/code> yolu \u00fczerinde yap\u0131land\u0131r\u0131r. <code>context<\/code> \u00f6zelli\u011fi sayesinde <code>prisma<\/code> istemcisini t\u00fcm \u00e7\u00f6z\u00fcmleyicilere kolayca iletebiliriz. <code>dotenv\/config<\/code> ile <code>.env<\/code> dosyas\u0131ndaki ortam de\u011fi\u015fkenlerinin y\u00fcklenmesini sa\u011fl\u0131yoruz.<\/p>\n<p>Backend projesini \u00e7al\u0131\u015ft\u0131rmak i\u00e7in <code>package.json<\/code> dosyan\u0131za a\u015fa\u011f\u0131daki script&#8217;leri ekleyebilirsiniz:<\/p>\n<pre><code class=\"language-json\">\/\/ package.json\n{\n  \"name\": \"recipe-app-backend\",\n  \"version\": \"1.0.0\",\n  \"main\": \"dist\/index.js\",\n  \"scripts\": {\n    \"build\": \"npx tsc\",\n    \"start\": \"node dist\/index.js\",\n    \"dev\": \"nodemon --exec ts-node src\/index.ts\"\n  },\n  \/\/ ... di\u011fer ba\u011f\u0131ml\u0131l\u0131klar\n}<\/code><\/pre>\n<p>\u015eimdi <code>npm run dev<\/code> komutunu \u00e7al\u0131\u015ft\u0131rarak GraphQL sunucunuzu ba\u015flatabilirsiniz. <code>http:\/\/localhost:4000\/graphql<\/code> adresine giderek GraphiQL aray\u00fcz\u00fcn\u00fc g\u00f6rebilir ve sorgular\u0131n\u0131z\u0131 test edebilirsiniz.<\/p>\n<h2>React Frontend Entegrasyonu<\/h2>\n<p>Frontend uygulamam\u0131zda GraphQL API&#8217;mizle etkile\u015fim kurmak i\u00e7in Apollo Client&#8217;\u0131 kullanaca\u011f\u0131z.<\/p>\n<h3>Apollo Client Kurulumu<\/h3>\n<p>React projemizin k\u00f6k dizininde (recipe-app-frontend) Apollo Client&#8217;\u0131 kural\u0131m:<\/p>\n<pre><code class=\"language-bash\">cd recipe-app-frontend\nnpm install @apollo\/client graphql<\/code><\/pre>\n<p><code>src\/main.tsx<\/code> veya <code>src\/index.tsx<\/code> dosyas\u0131n\u0131 g\u00fcncelleyerek <code>ApolloProvider<\/code> ile uygulamam\u0131z\u0131 sarmalayaca\u011f\u0131z:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/main.tsx (Vite i\u00e7in)\nimport React from 'react';\nimport ReactDOM from 'react-dom\/client';\nimport App from '.\/App.tsx';\nimport '.\/index.css';\n\nimport { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo\/client';\n\nconst client = new ApolloClient({\n  uri: 'http:\/\/localhost:4000\/graphql', \/\/ GraphQL sunucumuzun adresi\n  cache: new InMemoryCache(),\n});\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n  <React.StrictMode>\n    <ApolloProvider client={client}>\n      <App \/>\n    <\/ApolloProvider>\n  <\/React.StrictMode>,\n);<\/code><\/pre>\n<p>Bu yap\u0131land\u0131rma, <code>App<\/code> bile\u015fenimiz ve alt bile\u015fenlerinin t\u00fcm\u00fcn\u00fcn Apollo Client&#8217;a eri\u015fmesini sa\u011flar.<\/p>\n<h3>Veri \u00c7ekme (Queries)<\/h3>\n<p>GraphQL sorgular\u0131n\u0131 React bile\u015fenlerimizde kullanmak i\u00e7in <code>@apollo\/client<\/code> k\u00fct\u00fcphanesinin <code>useQuery<\/code> hook&#8217;unu kullanaca\u011f\u0131z. T\u00fcm tarifleri listeleyen bir <code>RecipeList<\/code> bile\u015feni olu\u015ftural\u0131m:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/components\/RecipeList.tsx\nimport React from 'react';\nimport { useQuery, gql } from '@apollo\/client';\n\nconst GET_RECIPES = gql<code>\n  query GetRecipes {\n    recipes {\n      id\n      title\n      description\n      imageUrl\n      prepTime\n      cookTime\n      servings\n    }\n  }\n<\/code>;\n\ninterface Recipe {\n  id: string;\n  title: string;\n  description?: string;\n  imageUrl?: string;\n  prepTime?: number;\n  cookTime?: number;\n  servings?: number;\n}\n\nfunction RecipeList() {\n  const { loading, error, data } = useQuery<{ recipes: Recipe[] }>(GET_RECIPES);\n\n  if (loading) return <p>Y\u00fckleniyor...<\/p>;\n  if (error) return <p>Hata: {error.message}<\/p>;\n\n  return (\n    <div>\n      <h2>T\u00fcm Tarifler<\/h2>\n      <div className=\"recipe-grid\">\n        {data?.recipes.map((recipe) => (\n          <div key={recipe.id} className=\"recipe-card\">\n            {recipe.imageUrl && <img src={recipe.imageUrl} alt={recipe.title} \/>}\n            <h3>{recipe.title}<\/h3>\n            <p>{recipe.description}<\/p>\n            {\/<em> Di\u011fer detaylar eklenebilir <\/em>\/}\n          <\/div>\n        ))}\n      <\/div>\n    <\/div>\n  );\n}\n\nexport default RecipeList;<\/code><\/pre>\n<p><code>useQuery<\/code> hook&#8217;u <code>loading<\/code>, <code>error<\/code> ve <code>data<\/code> nesnelerini d\u00f6nd\u00fcr\u00fcr. Bu sayede uygulaman\u0131z\u0131n y\u00fcklenme, hata ve veri durumlar\u0131n\u0131 kolayca y\u00f6netebilirsiniz.<\/p>\n<p>Tek bir tarifi g\u00f6r\u00fcnt\u00fclemek i\u00e7in <code>RecipeDetail<\/code> bile\u015fenini ve <code>useQuery<\/code> hook&#8217;unu kullanabiliriz.<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/components\/RecipeDetail.tsx\nimport React from 'react';\nimport { useQuery, gql } from '@apollo\/client';\nimport { useParams } from 'react-router-dom'; \/\/ React Router kullan\u0131yorsan\u0131z\n\nconst GET_RECIPE_BY_ID = gql<code>\n  query GetRecipeById($id: ID!) {\n    recipe(id: $id) {\n      id\n      title\n      description\n      instructions\n      prepTime\n      cookTime\n      servings\n      category\n      imageUrl\n      ingredients {\n        id\n        name\n        quantity\n      }\n    }\n  }\n<\/code>;\n\ninterface Ingredient {\n  id: string;\n  name: string;\n  quantity?: string;\n}\n\ninterface RecipeDetailType {\n  id: string;\n  title: string;\n  description?: string;\n  instructions: string;\n  prepTime?: number;\n  cookTime?: number;\n  servings?: number;\n  category?: string;\n  imageUrl?: string;\n  ingredients: Ingredient[];\n}\n\nfunction RecipeDetail() {\n  const { id } = useParams<{ id: string }>(); \/\/ URL'den id'yi al\n  const { loading, error, data } = useQuery<{ recipe: RecipeDetailType }>(GET_RECIPE_BY_ID, {\n    variables: { id },\n  });\n\n  if (loading) return <p>Tarif y\u00fckleniyor...<\/p>;\n  if (error) return <p>Hata: {error.message}<\/p>;\n  if (!data?.recipe) return <p>Tarif bulunamad\u0131.<\/p>;\n\n  const { recipe } = data;\n\n  return (\n    <div className=\"recipe-detail\">\n      <h2>{recipe.title}<\/h2>\n      {recipe.imageUrl && <img src={recipe.imageUrl} alt={recipe.title} \/>}\n      <p><strong>A\u00e7\u0131klama:<\/strong> {recipe.description}<\/p>\n      <p><strong>Haz\u0131rl\u0131k S\u00fcresi:<\/strong> {recipe.prepTime ? <code>${recipe.prepTime} dk<\/code> : 'Belirtilmemi\u015f'}<\/p>\n      <p><strong>Pi\u015firme S\u00fcresi:<\/strong> {recipe.cookTime ? <code>${recipe.cookTime} dk<\/code> : 'Belirtilmemi\u015f'}<\/p>\n      <p><strong>Porsiyon:<\/strong> {recipe.servings || 'Belirtilmemi\u015f'}<\/p>\n      <p><strong>Kategori:<\/strong> {recipe.category || 'Belirtilmemi\u015f'}<\/p>\n\n      <h3>Malzemeler:<\/h3>\n      <ul>\n        {recipe.ingredients.map((ingredient) => (\n          <li key={ingredient.id}>\n            {ingredient.quantity} {ingredient.name}\n          <\/li>\n        ))}\n      <\/ul>\n\n      <h3>Haz\u0131rlan\u0131\u015f\u0131:<\/h3>\n      <p>{recipe.instructions}<\/p>\n    <\/div>\n  );\n}\n\nexport default RecipeDetail;<\/code><\/pre>\n<p>Bu bile\u015fen, URL&#8217;den tarifin ID&#8217;sini al\u0131r ve bu ID ile GraphQL API&#8217;mizden ilgili tarifi \u00e7eker.<\/p>\n<h3>Veri G\u00f6nderme (Mutations)<\/h3>\n<p>Yeni tarif ekleme veya mevcut tarifleri g\u00fcncelleme gibi i\u015flemler i\u00e7in <code>useMutation<\/code> hook&#8217;unu kullanaca\u011f\u0131z. Bir <code>RecipeForm<\/code> bile\u015feni olu\u015ftural\u0131m:<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/components\/RecipeForm.tsx\nimport React, { useState } from 'react';\nimport { useMutation, gql } from '@apollo\/client';\nimport { useNavigate } from 'react-router-dom';\n\nconst CREATE_RECIPE = gql<code>\n  mutation CreateRecipe($input: CreateRecipeInput!) {\n    createRecipe(input: $input) {\n      id\n      title\n      description\n      imageUrl\n    }\n  }\n<\/code>;\n\nconst GET_RECIPES = gql<code>\n  query GetRecipes {\n    recipes {\n      id\n      title\n      description\n      imageUrl\n    }\n  }\n<\/code>;\n\nfunction RecipeForm() {\n  const navigate = useNavigate();\n  const [formData, setFormData] = useState({\n    title: '',\n    description: '',\n    instructions: '',\n    prepTime: '',\n    cookTime: '',\n    servings: '',\n    category: '',\n    imageUrl: '',\n    ingredients: [{ name: '', quantity: '' }],\n  });\n\n  const [createRecipe, { loading, error }] = useMutation(CREATE_RECIPE, {\n    refetchQueries: [{ query: GET_RECIPES }], \/\/ Yeni tarif eklendi\u011finde liste g\u00fcncellensin\n    onCompleted: () => {\n      navigate('\/'); \/\/ Ba\u015far\u0131l\u0131 olursa ana sayfaya y\u00f6nlendir\n    },\n  });\n\n  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n    const { name, value } = e.target;\n    setFormData((prev) => ({ ...prev, [name]: value }));\n  };\n\n  const handleIngredientChange = (index: number, e: React.ChangeEvent<HTMLInputElement>) => {\n    const { name, value } = e.target;\n    const newIngredients = [...formData.ingredients];\n    newIngredients[index] = { ...newIngredients[index], [name]: value };\n    setFormData((prev) => ({ ...prev, ingredients: newIngredients }));\n  };\n\n  const addIngredient = () => {\n    setFormData((prev) => ({\n      ...prev,\n      ingredients: [...prev.ingredients, { name: '', quantity: '' }],\n    }));\n  };\n\n  const removeIngredient = (index: number) => {\n    const newIngredients = formData.ingredients.filter((_, i) => i !== index);\n    setFormData((prev) => ({ ...prev, ingredients: newIngredients }));\n  };\n\n  const handleSubmit = async (e: React.FormEvent) => {\n    e.preventDefault();\n    try {\n      await createRecipe({\n        variables: {\n          input: {\n            ...formData,\n            prepTime: formData.prepTime ? parseInt(formData.prepTime) : null,\n            cookTime: formData.cookTime ? parseInt(formData.cookTime) : null,\n            servings: formData.servings ? parseInt(formData.servings) : null,\n            ingredients: formData.ingredients.filter(ing => ing.name.trim() !== ''),\n          },\n        },\n      });\n    } catch (err) {\n      console.error(\"Tarif olu\u015fturulurken hata olu\u015ftu:\", err);\n    }\n  };\n\n  return (\n    <form onSubmit={handleSubmit} className=\"recipe-form\">\n      <h2>Yeni Tarif Ekle<\/h2>\n      {error && <p className=\"error-message\">Hata: {error.message}<\/p>}\n\n      <label>\n        Ba\u015fl\u0131k:\n        <input type=\"text\" name=\"title\" value={formData.title} onChange={handleChange} required \/>\n      <\/label>\n      <label>\n        A\u00e7\u0131klama:\n        <textarea name=\"description\" value={formData.description} onChange={handleChange}><\/textarea>\n      <\/label>\n      <label>\n        Haz\u0131rlan\u0131\u015f\u0131:\n        <textarea name=\"instructions\" value={formData.instructions} onChange={handleChange} required><\/textarea>\n      <\/label>\n      <label>\n        Haz\u0131rl\u0131k S\u00fcresi (dk):\n        <input type=\"number\" name=\"prepTime\" value={formData.prepTime} onChange={handleChange} \/>\n      <\/label>\n      <label>\n        Pi\u015firme S\u00fcresi (dk):\n        <input type=\"number\" name=\"cookTime\" value={formData.cookTime} onChange={handleChange} \/>\n      <\/label>\n      <label>\n        Porsiyon:\n        <input type=\"number\" name=\"servings\" value={formData.servings} onChange={handleChange} \/>\n      <\/label>\n      <label>\n        Kategori:\n        <input type=\"text\" name=\"category\" value={formData.category} onChange={handleChange} \/>\n      <\/label>\n      <label>\n        Resim URL'si:\n        <input type=\"url\" name=\"imageUrl\" value={formData.imageUrl} onChange={handleChange} \/>\n      <\/label>\n\n      <h3>Malzemeler<\/h3>\n      {formData.ingredients.map((ingredient, index) => (\n        <div key={index} className=\"ingredient-input-group\">\n          <input\n            type=\"text\"\n            name=\"name\"\n            placeholder=\"Malzeme Ad\u0131\"\n            value={ingredient.name}\n            onChange={(e) => handleIngredientChange(index, e)}\n            required\n          \/>\n          <input\n            type=\"text\"\n            name=\"quantity\"\n            placeholder=\"Miktar (\u00f6rn: 2 su barda\u011f\u0131)\"\n            value={ingredient.quantity}\n            onChange={(e) => handleIngredientChange(index, e)}\n          \/>\n          <button type=\"button\" onClick={() => removeIngredient(index)}>Kald\u0131r<\/button>\n        <\/div>\n      ))}\n      <button type=\"button\" onClick={addIngredient}>Malzeme Ekle<\/button>\n\n      <button type=\"submit\" disabled={loading}>\n        {loading ? 'Ekleniyor...' : 'Tarifi Ekle'}\n      <\/button>\n    <\/form>\n  );\n}\n\nexport default RecipeForm;<\/code><\/pre>\n<p><code>useMutation<\/code> hook&#8217;u, bir mutasyon fonksiyonu (<code>createRecipe<\/code>) ve mutasyonun durumu (<code>loading<\/code>, <code>error<\/code>) gibi bilgileri d\u00f6nd\u00fcr\u00fcr. <code>refetchQueries<\/code> se\u00e7ene\u011fi, mutasyon tamamland\u0131\u011f\u0131nda belirli sorgular\u0131n yeniden \u00e7al\u0131\u015ft\u0131r\u0131lmas\u0131n\u0131 sa\u011flayarak \u00f6nbelle\u011fi g\u00fcnceller. <code>onCompleted<\/code> geri \u00e7a\u011f\u0131rma fonksiyonu ile mutasyon ba\u015far\u0131yla tamamland\u0131\u011f\u0131nda y\u00f6nlendirme gibi i\u015flemler yapabiliriz.<\/p>\n<h3>Aray\u00fcz Bile\u015fenleri<\/h3>\n<p>Yukar\u0131daki <code>RecipeList<\/code>, <code>RecipeDetail<\/code> ve <code>RecipeForm<\/code> bile\u015fenlerini <code>src\/App.tsx<\/code> i\u00e7inde veya React Router kullanarak farkl\u0131 rotalara ba\u011flayarak tam bir uygulama olu\u015fturabilirsiniz.<\/p>\n<pre><code class=\"language-typescript\">\/\/ src\/App.tsx\nimport React from 'react';\nimport { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';\nimport RecipeList from '.\/components\/RecipeList';\nimport RecipeDetail from '.\/components\/RecipeDetail';\nimport RecipeForm from '.\/components\/RecipeForm';\nimport '.\/App.css'; \/\/ Basit stil dosyas\u0131\n\nfunction App() {\n  return (\n    <Router>\n      <div className=\"container\">\n        <nav>\n          <ul>\n            <li>\n              <Link to=\"\/\">Tarifler<\/Link>\n            <\/li>\n            <li>\n              <Link to=\"\/add-recipe\">Tarif Ekle<\/Link>\n            <\/li>\n          <\/ul>\n        <\/nav>\n\n        <Routes>\n          <Route path=\"\/\" element={<RecipeList \/>} \/>\n          <Route path=\"\/recipe\/:id\" element={<RecipeDetail \/>} \/>\n          <Route path=\"\/add-recipe\" element={<RecipeForm \/>} \/>\n          {\/<em> D\u00fczenleme rotas\u0131 da eklenebilir: <Route path=\"\/edit-recipe\/:id\" element={<RecipeEditForm \/>} \/> <\/em>\/}\n        <\/Routes>\n      <\/div>\n    <\/Router>\n  );\n}\n\nexport default App;<\/code><\/pre>\n<p>Bu, uygulaman\u0131n temel navigasyonunu ve farkl\u0131 sayfalar aras\u0131ndaki ge\u00e7i\u015fleri sa\u011flar.<\/p>\n<h2>Geli\u015fmi\u015f Konular ve \u0130yile\u015ftirmeler<\/h2>\n<p>Uygulamam\u0131z\u0131 daha sa\u011flam, g\u00fcvenli ve kullan\u0131c\u0131 dostu hale getirmek i\u00e7in baz\u0131 geli\u015fmi\u015f konulara de\u011finmekte fayda var.<\/p>\n<h3>Kimlik Do\u011frulama ve Yetkilendirme<\/h3>\n<p>Bir yemek tarifi uygulamas\u0131nda, kullan\u0131c\u0131lar\u0131n kendi tariflerini eklemesi, d\u00fczenlemesi veya silmesi i\u00e7in kimlik do\u011frulama ve yetkilendirme mekanizmalar\u0131 gereklidir. JWT (JSON Web Tokens) genellikle bu ama\u00e7la kullan\u0131l\u0131r.<br \/>\n*   <strong>Backend:<\/strong> Kullan\u0131c\u0131 kayd\u0131 ve giri\u015fi i\u00e7in mutasyonlar olu\u015fturulur. Giri\u015f yap\u0131ld\u0131\u011f\u0131nda, sunucu bir JWT token&#8217;\u0131 d\u00f6nd\u00fcr\u00fcr. Bu token, sonraki isteklerde <code>Authorization<\/code> ba\u015fl\u0131\u011f\u0131nda g\u00f6nderilir. GraphQL <code>context<\/code> i\u00e7inde, gelen iste\u011fin <code>Authorization<\/code> ba\u015fl\u0131\u011f\u0131ndan token&#8217;\u0131 ayr\u0131\u015ft\u0131r\u0131p kullan\u0131c\u0131 bilgilerini \u00e7\u00f6z\u00fcmleyicilere iletebilirsiniz. \u00c7\u00f6z\u00fcmleyicilerde, kullan\u0131c\u0131n\u0131n belirli bir i\u015flemi yapmaya yetkili olup olmad\u0131\u011f\u0131n\u0131 kontrol edebilirsiniz.<br \/>\n*   <strong>Frontend:<\/strong> Kullan\u0131c\u0131 giri\u015f yapt\u0131ktan sonra al\u0131nan JWT token&#8217;\u0131 <code>localStorage<\/code> veya <code>sessionStorage<\/code> gibi yerel depolarda saklan\u0131r. Apollo Client, her GraphQL iste\u011fine bu token&#8217;\u0131 eklemek i\u00e7in bir <code>ApolloLink<\/code> kullanabilir.<\/p>\n<h3>Hata Y\u00f6netimi<\/h3>\n<p>API&#8217;ler ve frontend uygulamalar\u0131 aras\u0131ndaki ileti\u015fimde hatalar ka\u00e7\u0131n\u0131lmazd\u0131r. GraphQL, standart bir hata format\u0131 sunar.<br \/>\n*   <strong>Backend:<\/strong> Prisma&#8217;dan gelen veritaban\u0131 hatalar\u0131 veya i\u015f mant\u0131\u011f\u0131 hatalar\u0131, GraphQL hata format\u0131na uygun olarak istemciye iletilmelidir. <code>apollo-server<\/code> varsay\u0131lan olarak bu hatalar\u0131 i\u015fler, ancak \u00f6zel hata mesajlar\u0131 veya kodlar\u0131 tan\u0131mlayarak daha anlaml\u0131 geri bildirimler sa\u011flayabilirsiniz.<br \/>\n*   <strong>Frontend:<\/strong> <code>useQuery<\/code> ve <code>useMutation<\/code> hook&#8217;lar\u0131n\u0131n <code>error<\/code> nesnesi sayesinde, hatalar\u0131 kullan\u0131c\u0131 aray\u00fcz\u00fcnde g\u00f6sterebilirsiniz. Kullan\u0131c\u0131ya net ve anla\u015f\u0131l\u0131r hata mesajlar\u0131 sunmak, kullan\u0131c\u0131 deneyimi a\u00e7\u0131s\u0131ndan kritik \u00f6neme sahiptir.<\/p>\n<h3>Sayfalama ve Filtreleme<\/h3>\n<p>\u00c7ok say\u0131da tarif oldu\u011funda, t\u00fcm\u00fcn\u00fc tek seferde y\u00fcklemek performans sorunlar\u0131na yol a\u00e7abilir.<br \/>\n*   <strong>Sayfalama:<\/strong> <code>offset-based<\/code> (skip\/take) veya <code>cursor-based<\/code> (after\/before) sayfalama teknikleri kullan\u0131labilir. GraphQL sorgular\u0131n\u0131za <code>limit<\/code>, <code>offset<\/code> veya <code>after<\/code> gibi arg\u00fcmanlar ekleyerek sunucunun yaln\u0131zca belirli bir veri dilimini d\u00f6nd\u00fcrmesini sa\u011flayabilirsiniz.<br \/>\n*   <strong>Filtreleme ve S\u0131ralama:<\/strong> GraphQL sorgular\u0131na <code>filter<\/code> veya <code>orderBy<\/code> gibi arg\u00fcmanlar ekleyerek kullan\u0131c\u0131lar\u0131n tarifleri kategoriye, pi\u015firme s\u00fcresine veya ba\u015fl\u0131\u011fa g\u00f6re filtrelemesine ve s\u0131ralamas\u0131na olanak tan\u0131yabilirsiniz. Prisma, <code>findMany<\/code> metodunda bu t\u00fcr filtreleme ve s\u0131ralama se\u00e7eneklerini kolayca sunar.<\/p>\n<h3>Ger\u00e7ek Zamanl\u0131 G\u00fcncellemeler (Subscriptions)<\/h3>\n<p>GraphQL Subscriptions, WebSocket&#8217;ler arac\u0131l\u0131\u011f\u0131yla ger\u00e7ek zamanl\u0131 veri g\u00fcncellemeleri sa\u011flamak i\u00e7in kullan\u0131labilir. \u00d6rne\u011fin, yeni bir tarif eklendi\u011finde veya mevcut bir tarif g\u00fcncellendi\u011finde, t\u00fcm ba\u011fl\u0131 istemcilere an\u0131nda bildirim g\u00f6nderebilirsiniz. Bu, sohbet uygulamalar\u0131 veya canl\u0131 bildirimler gibi senaryolarda \u00e7ok kullan\u0131\u015fl\u0131d\u0131r. Apollo Server, Subscriptions i\u00e7in kolay entegrasyon sunar.<\/p>\n<h3>Test Etme<\/h3>\n<p>Uygulaman\u0131n g\u00fcvenilirli\u011fini sa\u011flamak i\u00e7in testler yazmak \u00f6nemlidir.<br \/>\n*   <strong>Frontend:<\/strong> React Testing Library ve Jest kullanarak bile\u015fenlerinizi ve kullan\u0131c\u0131 etkile\u015fimlerini test edebilirsiniz. Apollo Client&#8217;\u0131n <code>MockedProvider<\/code>&#8216;\u0131, GraphQL sorgular\u0131n\u0131 taklit ederek bile\u015fen testlerini kolayla\u015ft\u0131r\u0131r.<br \/>\n*   <strong>Backend:<\/strong> Jest veya Mocha gibi test \u00e7at\u0131s\u0131 ile GraphQL \u00e7\u00f6z\u00fcmleyicilerinizi ve Prisma ile veritaban\u0131 etkile\u015fimlerinizi test edebilirsiniz. Entegrasyon testleri, API&#8217;nizin u\u00e7tan uca do\u011fru \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 do\u011frular.<\/p>\n<h3>Da\u011f\u0131t\u0131m (Deployment)<\/h3>\n<p>Uygulaman\u0131z\u0131 canl\u0131ya almak i\u00e7in frontend ve backend&#8217;i ayr\u0131 ayr\u0131 da\u011f\u0131tman\u0131z gerekir.<br \/>\n*   <strong>Frontend (React):<\/strong> Vercel, Netlify veya AWS Amplify gibi servisler, statik React uygulamalar\u0131n\u0131 da\u011f\u0131tmak i\u00e7in m\u00fckemmel se\u00e7eneklerdir. <code>npm run build<\/code> komutuyla olu\u015fturulan statik dosyalar\u0131 bu servislere y\u00fcklemeniz yeterlidir.<br \/>\n*   <strong>Backend (Node.js\/GraphQL):<\/strong> Render, Heroku, AWS EC2, DigitalOcean Droplets veya Google Cloud Run gibi platformlar, Node.js sunucular\u0131n\u0131 bar\u0131nd\u0131rmak i\u00e7in kullan\u0131labilir. Veritaban\u0131 olarak da bulut tabanl\u0131 bir PostgreSQL (\u00f6rne\u011fin Render PostgreSQL, Supabase, Railway) kullanmak, y\u00f6netim y\u00fck\u00fcn\u00fc azalt\u0131r.<\/p>\n<h2>Sonu\u00e7<\/h2>\n<p>Bu makalede, React, Prisma ve GraphQL gibi modern ve g\u00fc\u00e7l\u00fc teknolojileri bir araya getirerek dinamik bir yemek tarifi uygulamas\u0131 olu\u015fturma s\u00fcrecini detayl\u0131 bir \u015fekilde inceledik. Proje kurulumundan veritaban\u0131 \u015femas\u0131 tan\u0131mlamaya, GraphQL sunucusu ve \u00e7\u00f6z\u00fcmleyicileri olu\u015fturmaktan React frontend&#8217;ini entegre etmeye kadar her ad\u0131m\u0131 ad\u0131m ad\u0131m ele ald\u0131k. Ayr\u0131ca, kimlik do\u011frulama, hata y\u00f6netimi, sayfalama ve da\u011f\u0131t\u0131m gibi geli\u015fmi\u015f konulara da de\u011finerek uygulaman\u0131z\u0131n daha sa\u011flam ve \u00fcretime haz\u0131r hale gelmesi i\u00e7in gerekli bilgileri sunduk.<\/p>\n<p>Bu teknoloji y\u0131\u011f\u0131n\u0131, geli\u015ftiricilere hem frontend hem de backend taraf\u0131nda e\u015fsiz bir verimlilik, esneklik ve tip g\u00fcvenli\u011fi sunar. GraphQL&#8217;in esnek veri sorgulama yetene\u011fi, Prisma&#8217;n\u0131n modern ORM \u00f6zellikleri ve React&#8217;\u0131n bile\u015fen tabanl\u0131 mimarisi, karma\u015f\u0131k uygulamalar\u0131n bile h\u0131zl\u0131 ve hatas\u0131z bir \u015fekilde geli\u015ftirilmesini m\u00fcmk\u00fcn k\u0131lar. Bu yakla\u015f\u0131m, sadece yemek tarifi uygulamalar\u0131 i\u00e7in de\u011fil, veri odakl\u0131 bir\u00e7ok farkl\u0131 web uygulamas\u0131 i\u00e7in de uygulanabilir ve gelece\u011fe y\u00f6nelik, \u00f6l\u00e7eklenebilir \u00e7\u00f6z\u00fcmler \u00fcretmenize olanak tan\u0131r. Bu rehberin, kendi projelerinizi geli\u015ftirirken size ilham vermesini ve yol g\u00f6stermesini umuyoruz.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?\nGiri\u015f\nG\u00fcn\u00fcm\u00fcz\u00fcn h\u0131zla de\u011fi\u015fen dijital d\u00fcnyas\u0131nda, kullan\u0131c","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[128],"tags":[],"class_list":{"0":"post-38619","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-react","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?\" \/>\n<meta property=\"og:description\" content=\"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? Giri\u015f G\u00fcn\u00fcm\u00fcz\u00fcn h\u0131zla de\u011fi\u015fen dijital d\u00fcnyas\u0131nda, kullan\u0131c\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-04T05:40:55+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?\",\"datePublished\":\"2026-02-04T05:40:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/\"},\"wordCount\":2507,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"React\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/\",\"name\":\"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-02-04T05:40:55+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/","og_locale":"tr_TR","og_type":"article","og_title":"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?","og_description":"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? Giri\u015f G\u00fcn\u00fcm\u00fcz\u00fcn h\u0131zla de\u011fi\u015fen dijital d\u00fcnyas\u0131nda, kullan\u0131c","og_url":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-02-04T05:40:55+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"19 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?","datePublished":"2026-02-04T05:40:55+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/"},"wordCount":2507,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["React"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/","url":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/","name":"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-02-04T05:40:55+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/react-prisma-ve-graphql-ile-bir-yemek-tarifi-uygulamasi-nasil-gelistirilir\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"React, Prisma ve GraphQL ile Bir Yemek Tarifi Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38619","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=38619"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38619\/revisions"}],"predecessor-version":[{"id":38620,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38619\/revisions\/38620"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=38619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=38619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=38619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}