Takip et

Next.js 14’te Supabase SSR Kurulumunun En Kolay Yolu

Modern web uygulamaları geliştirirken, hızlı yükleme süreleri, SEO uyumluluğu ve gelişmiş kullanıcı deneyimi kritik öneme sahiptir. Next.js 14, s…

Next.js 14’te Supabase SSR Kurulumunun En Kolay Yolu

Modern web uygulamaları geliştirirken, hızlı yükleme süreleri, SEO uyumluluğu ve gelişmiş kullanıcı deneyimi kritik öneme sahiptir. Next.js 14, sunucu tarafı oluşturma (SSR) yetenekleri ve sunucu bileşenleri (Server Components) ile bu hedeflere ulaşmayı kolaylaştırırken, Supabase ise açık kaynaklı bir Firebase alternatifi olarak veritabanı, kimlik doğrulama ve gerçek zamanlı abonelik gibi birçok arka uç hizmetini tek bir çatı altında sunar. Bu makalede, Next.js 14 projenizde Supabase’i SSR ile nasıl kolayca entegre edebileceğinizi, adım adım ve pratik örneklerle ele alacağız. Amacımız, hem verimli hem de ölçeklenebilir bir uygulama altyapısı kurmanıza yardımcı olmaktır.

Supabase Nedir ve Neden SSR ile Kullanılmalı?

Supabase’e Kısa Bir Bakış

Supabase, geliştiricilere güçlü ve esnek bir arka uç çözümü sunan açık kaynaklı bir platformdur. PostgreSQL veritabanı üzerine kurulu olup, GraphQL benzeri bir API (PostgREST), gerçek zamanlı abonelikler, kimlik doğrulama (Auth), depolama (Storage) ve sunucusuz fonksiyonlar (Edge Functions) gibi birçok hizmeti barındırır. Bu sayede, geliştiriciler arka uç karmaşıklıklarıyla uğraşmak yerine doğrudan uygulama mantığına odaklanabilirler. Supabase’in sunduğu hizmetler, özellikle hızlı prototipleme ve MVP (Minimum Viable Product) geliştirmek için idealdir.

Sunucu Tarafı Oluşturma (SSR) Nedir ve Avantajları

Sunucu Tarafı Oluşturma (SSR), bir web sayfasının HTML’inin istemciye gönderilmeden önce sunucuda oluşturulması işlemidir. Bu yaklaşım, sayfanın ilk yüklenmesinde boş bir HTML yerine, içeriği dolu bir HTML’in gelmesini sağlar. SSR’ın başlıca avantajları şunlardır:

  • Daha Hızlı İlk Yükleme: Kullanıcılar, JavaScript’in yüklenmesini ve çalışmasını beklemek zorunda kalmadan içeriği hemen görürler.
  • SEO İyileştirmeleri: Arama motoru botları, tam içeriğe sahip sayfaları daha kolay tarayabilir ve indeksleyebilir. Bu, arama motoru sıralamalarında avantaj sağlar.
  • Gelişmiş Kullanıcı Deneyimi: Özellikle yavaş internet bağlantısı olan veya eski cihaz kullanan kullanıcılar için daha akıcı bir deneyim sunar.
  • Veri Güvenliği: Hassas verilerin doğrudan istemci tarafında değil, sunucu tarafında işlenmesi ve render edilmesi daha güvenli bir ortam sağlar.

Supabase ve SSR’ın Birlikteliği Neden Güçlü?

Supabase’in sunduğu veri ve kimlik doğrulama hizmetlerini Next.js’in SSR yetenekleriyle birleştirmek, uygulamanız için birçok avantaj sunar. Sunucu tarafında Supabase’ten veri çekmek, bu verilerin doğrudan HTML’e gömülmesini sağlar. Bu, istemcinin ekstra bir API çağrısı yapmasını engeller ve sayfanın daha hızlı ve eksiksiz yüklenmesini sağlar. Ayrıca, kimlik doğrulama bilgilerini sunucu tarafında yönetmek, oturum güvenliğini artırır ve kullanıcı deneyimini kesintisiz hale getirir.

Next.js 14’ün SSR Yetenekleri

Next.js 14, App Router ile birlikte gelen Server Components ve Server Actions gibi özelliklerle SSR’ı daha da güçlendirdi. Server Components, veriyi doğrudan sunucuda çekip render etme yeteneği sunarak istemci tarafındaki JavaScript yükünü azaltır. Bu sayede, Supabase ile etkileşimleriniz doğrudan sunucuda gerçekleşir, bu da hem performans hem de güvenlik açısından önemli avantajlar sağlar.

Next.js 14 Projesi Oluşturma ve Gerekli Bağımlılıkları Kurma

Yeni Bir Next.js Uygulaması Başlatma

Öncelikle, Next.js 14 ile yeni bir proje oluşturalım. Terminalinizi açın ve aşağıdaki komutu çalıştırın:

npx create-next-app@latest nextjs-supabase-ssr-app --ts --eslint --app

Kurulum sırasında size bazı sorular sorulacaktır. TypeScript, ESLint ve App Router'ı (--app bayrağı ile) kullanacağımızı varsayarak ilerleyebiliriz. Proje adı olarak nextjs-supabase-ssr-app kullanabiliriz.

Proje oluştuktan sonra, dizine girin:

cd nextjs-supabase-ssr-app

Supabase Bağımlılıklarını Yükleme

Supabase ile etkileşim kurmak için gerekli olan istemci kütüphanelerini yüklememiz gerekiyor. Bu kütüphaneler hem sunucu hem de istemci tarafında Supabase API'sine erişim sağlar.

npm install @supabase/supabase-js @supabase/ssr

  • @supabase/supabase-js: Supabase hizmetleriyle etkileşim kurmak için temel JavaScript istemcisi.
  • @supabase/ssr: Next.js gibi SSR çerçeveleriyle Supabase'i güvenli ve verimli bir şekilde kullanmak için özel olarak tasarlanmış yardımcı kütüphane. Özellikle sunucu tarafında çerez tabanlı oturum yönetimi için önemlidir.

Proje Yapısına Genel Bakış

Next.js 14 App Router yapısı, dosya tabanlı yönlendirme ve özel klasörler aracılığıyla sunucu ve istemci bileşenlerini yönetmeyi kolaylaştırır. Projenizin temel yapısı şu şekilde olacaktır:

nextjs-supabase-ssr-app/
├── app/
│   ├── layout.tsx
│   ├── page.tsx
│   └── globals.css
├── public/
├── .env.local
├── package.json
└── tsconfig.json

Biz, Supabase istemcisini ve ilgili yardımcı fonksiyonları düzenlemek için genellikle lib/ veya utils/ gibi özel bir dizin oluşturmayı tercih edeceğiz. Örneğin, lib/supabase/ altında sunucu ve istemci için ayrı istemci örnekleri tanımlayabiliriz.

Supabase Projesi Oluşturma ve API Anahtarlarını Yapılandırma

Supabase Hesabı Oluşturma ve Yeni Proje Başlatma

Eğer henüz bir Supabase hesabınız yoksa, supabase.com adresine giderek ücretsiz bir hesap oluşturun. Hesabınıza giriş yaptıktan sonra "New project" butonuna tıklayarak yeni bir proje oluşturun. Proje oluştururken aşağıdaki bilgileri girmeniz istenecektir:

  • Name: Projenizin adı (örn. nextjs-ssr-demo)
  • Database Password: Güçlü bir şifre belirleyin ve not alın.
  • Region: Size en yakın bölgeyi seçin.
  • Pricing Plan: "Free" planı seçebilirsiniz.

Projeniz hazır olduğunda, Supabase paneline yönlendirileceksiniz.

API Anahtarlarını Bulma

Supabase projenizin paneline girdikten sonra, sol menüden "Project Settings" (Ayarlar) ve ardından "API" bölümüne gidin. Burada uygulamanızın Supabase ile iletişim kurması için gerekli olan API URL'sini ve anahtarlarını bulacaksınız.

İhtiyacımız olan anahtarlar şunlardır:

  • Project URL: https://[your-project-ref].supabase.co şeklinde bir URL.
  • Anon Public Key (anon): Bu anahtar, tarayıcıda doğrudan kullanılabilir ve Row-Level Security (RLS) kurallarınız tarafından kısıtlanan verilere erişim sağlar.
  • Service Role Key (service_role): Bu anahtar, bypass RLS özelliği taşır ve sadece sunucu tarafında, gizli tutulması gereken işlemlerde kullanılmalıdır. Kesinlikle istemci tarafında ifşa edilmemelidir!

Ortam Değişkenlerini (Environment Variables) Ayarlama

API anahtarlarınızı doğrudan kodunuza yazmak yerine, güvenlik ve esneklik açısından ortam değişkenleri olarak tanımlamak en iyi yaklaşımdır. Projenizin kök dizininde .env.local adında bir dosya oluşturun ve Supabase anahtarlarınızı buraya ekleyin:

NEXT_PUBLIC_SUPABASE_URL=https://[your-project-ref].supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_public_key

Önemli Not: Next.js'te NEXT_PUBLIC_ ile başlayan ortam değişkenleri istemci tarafında da erişilebilirken, diğerleri yalnızca sunucu tarafında erişilebilir. Supabase'in SSR kütüphanesi, oturum bilgilerini güvenli bir şekilde yönetmek için sunucu tarafında çalışır ve bu değişkenlere ihtiyaç duyar.

service_role anahtarını kullanmak isterseniz (ki bu sadece çok özel sunucu tarafı işlemler için olmalıdır), onu SUPABASE_SERVICE_ROLE_KEY=your_service_role_key şeklinde tanımlayabilirsiniz, ancak bu makalede daha çok anon anahtarı ile çalışacağız.

Supabase İstemcisini Sunucu Tarafında Yapılandırma

Supabase İstemci Modülü Oluşturma (Server-Side)

Next.js 14'te Supabase'i SSR ile kullanmanın anahtarı, Supabase istemcisini sunucu tarafında, her istek için yeni bir örnek oluşturarak yapılandırmaktır. Bu, özellikle kimlik doğrulama oturumlarını çerezler aracılığıyla yönetirken önemlidir. Projenizin kök dizininde lib/supabase/ adında bir klasör oluşturun ve içine server.ts adında bir dosya ekleyin:

// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
import { Database } from '@/types/supabase' // Tip güvenliği için

export function createClient() {
  const cookieStore = cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        get(name: string) {
          return cookieStore.get(name)?.value
        },
        set(name: string, value: string, options: any) {
          try {
            cookieStore.set({ name, value, ...options })
          } catch (error) {
            // Sunucu Bileşenlerinde 'set' işlemi desteklenmez.
            // Bu hata, sadece istemci tarafında çalışması gereken bir işlem olduğunda ortaya çıkar.
          }
        },
        remove(name: string, options: any) {
          try {
            cookieStore.set({ name, value: '', ...options })
          } catch (error) {
            // Sunucu Bileşenlerinde 'remove' işlemi desteklenmez.
          }
        },
      },
    }
  )
}

Bu kod parçacığı, Next.js'in cookies() fonksiyonunu kullanarak her istek için Supabase istemcisini oluşturur. Bu, Supabase'in oturum bilgilerini HTTP çerezleri aracılığıyla güvenli bir şekilde okuyup yazmasını sağlar.

Typescript ile Tip Güvenliği

Supabase, veritabanı şemanızdan otomatik olarak TypeScript tipleri oluşturmanıza olanak tanır. Bu, kodunuzda tip güvenliği sağlayarak hataları azaltır ve geliştirme sürecini hızlandırır.

  1. Supabase CLI'yi yükleyin:
    npm install -g supabase
    

  2. Projenizin kök dizininde, Supabase CLI'yi kullanarak tipleri oluşturun. Bu komutu çalıştırmadan önce Supabase projenizin URL ve anon key'inin ortam değişkenlerinde tanımlı olduğundan emin olun.
    supabase gen types typescript --project-id "your-project-ref" > types/supabase.ts
    


    your-project-ref yerine Supabase projenizin referans ID'sini (URL'deki kısmı) yazmalısınız. Bu komut, types/supabase.ts dosyasına veritabanı şemanızın TypeScript tiplerini yazacaktır. Daha sonra bu dosyayı lib/supabase/server.ts dosyasında import edebilirsiniz.

İstemcinin Kullanıma Hazırlanması

Artık createClient() fonksiyonunu herhangi bir sunucu bileşeninde veya sunucu eyleminde (Server Action) çağırarak Supabase istemcisine erişebiliriz. Bu istemci, çerezler aracılığıyla mevcut kullanıcı oturumunu otomatik olarak yönetecek ve veri çekme işlemlerini güvenli bir şekilde gerçekleştirecektir.

Veri Çekme: Sunucu Bileşenlerinde (Server Components) Supabase Kullanımı

Temel Veri Çekme Örneği

Supabase istemcisini oluşturduktan sonra, sunucu bileşenlerinizde veritabanından veri çekmek oldukça basittir. app/page.tsx dosyanızı aşağıdaki gibi güncelleyelim:

// app/page.tsx
import { createClient } from '@/lib/supabase/server' // Sunucu istemcisini import ediyoruz

export default async function Index() {
  const supabase = createClient() // Her istek için yeni bir istemci oluşturuyoruz

  const { data: todos, error } = await supabase
    .from('todos') // 'todos' tablosundan veri çekiyoruz
    .select('*') // Tüm sütunları seçiyoruz

  if (error) {
    console.error('Veri çekme hatası:', error)
    return 

Veri yüklenirken bir hata oluştu.

} return (

Yapılacaklar Listesi

    {todos?.map((todo) => (
  • {todo.title}
  • ))}
) }

Bu örnekte, createClient() fonksiyonunu çağırarak Supabase istemcisini alıyor ve doğrudan todos tablosundan veri çekiyoruz. Bu işlem sunucuda gerçekleştiği için, sayfa istemciye ulaştığında todos listesi zaten HTML'in içinde olacaktır.

Not: Bu örneğin çalışması için Supabase projenizde 'todos' adında bir tablo ve içinde bazı veriler olması gerekmektedir. Supabase panelinizden "Table Editor" bölümüne giderek hızlıca bir todos tablosu oluşturabilirsiniz (id, title, is_complete gibi sütunlarla).

Parametrelerle Veri Filtreleme

Veri çekerken filtreleme yapmak da oldukça kolaydır. Örneğin, sadece tamamlanmamış görevleri çekmek isteyebiliriz:

const { data: incompleteTodos, error } = await supabase
  .from('todos')
  .select('*')
  .eq('is_complete', false) // 'is_complete' sütunu 'false' olanları seç

Supabase sorgu oluşturucu, eq (eşit), gt (büyük), lt (küçük), ilike (benzer) gibi birçok operatör sunar.

Veri Ekleme ve Güncelleme İşlemleri

Veri ekleme ve güncelleme işlemleri genellikle kullanıcı etkileşimini gerektirdiğinden, bunları Server Actions kullanarak yapmak en iyi yaklaşımdır. Server Actions, doğrudan sunucuda çalışan ve istemci tarafında bir form gönderimi veya buton tıklamasıyla tetiklenebilen asenkron fonksiyonlardır.

// app/page.tsx (örnek bir Server Action)
import { createClient } from '@/lib/supabase/server'
import { revalidatePath } from 'next/cache' // Veri önbelleğini temizlemek için

export default async function Index() {
  const supabase = createClient()
  const { data: todos } = await supabase.from('todos').select('*')

  async function addTodo(formData: FormData) {
    'use server' // Bu fonksiyonun bir Server Action olduğunu belirtir
    const title = formData.get('title') as string
    const supabase = createClient() // Server Action içinde de istemci oluşturulur

    const { error } = await supabase.from('todos').insert({ title, is_complete: false })

    if (error) {
      console.error('Görev eklenirken hata oluştu:', error)
    } else {
      revalidatePath('/') // Veri değiştiği için ana sayfanın önbelleğini temizle
    }
  }

  return (
    

Yapılacaklar Listesi

    {todos?.map((todo) => (
  • {todo.title}
  • ))}
) }

Bu örnekte, addTodo adında bir Server Action tanımladık. Bu fonksiyon, bir form gönderimiyle tetiklenir, yeni bir görev ekler ve ardından revalidatePath('/') kullanarak ana sayfanın önbelleğini temizler, böylece kullanıcı güncel listeyi görür.

Hata Yönetimi

Supabase işlemleri sırasında oluşabilecek hataları yönetmek önemlidir. Her Supabase çağrısı, data ve error nesnelerini içeren bir obje döndürür. error nesnesi varsa, bir hata oluştuğu anlamına gelir ve bu hatayı uygun şekilde loglamalı veya kullanıcıya bildirmelisiniz.

const { data, error } = await supabase.from('my_table').select('*')

if (error) {
  // Hata durumunu yönet
  console.error('Supabase hatası:', error.message)
  // Kullanıcıya bir hata mesajı gösterebilirsiniz
} else {
  // Veriyi kullan
}

Kimlik Doğrulama (Authentication) SSR ile Entegre Etme

Oturum Yönetimi ve Çerezler

Supabase'in @supabase/ssr kütüphanesi, Next.js'in sunucu ortamında çerez tabanlı oturum yönetimini sorunsuz bir şekilde entegre eder. createClient() fonksiyonumuz, Next.js'in cookies() fonksiyonunu kullanarak oturum çerezlerini okur ve yazar. Bu, kullanıcı oturumunun sunucu tarafında güvenli bir şekilde korunmasını sağlar.

Kullanıcı Bilgilerini Sunucu Tarafında Çekme

Bir kullanıcının oturum bilgilerini veya profil verilerini sunucu tarafında çekmek, Next.js'in Server Components yapısı sayesinde oldukça basittir.

// app/dashboard/page.tsx (Örnek bir korumalı sayfa)
import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'

export default async function Dashboard() {
  const supabase = createClient()

  const {
    data: { user },
  } = await supabase.auth.getUser() // Mevcut kullanıcıyı çek

  if (!user) {
    // Kullanıcı oturum açmamışsa giriş sayfasına yönlendir
    redirect('/login')
  }

  // Kullanıcı varsa, profil bilgilerini veya diğer verileri çekebiliriz
  const { data: profile } = await supabase
    .from('profiles') // Kullanıcı profil tablonuz
    .select('*')
    .eq('id', user.id)
    .single()

  return (
    

Hoş Geldiniz, {user.email}!

{profile ? (

Profil Adı: {profile.username}

) : (

Profil bilgisi bulunamadı.

)}
) }

Bu örnekte, supabase.auth.getUser() ile mevcut kullanıcı oturumunu kontrol ediyoruz. Eğer kullanıcı oturum açmamışsa, redirect('/login') ile giriş sayfasına yönlendiriyoruz. Oturum açmışsa, kullanıcının e-posta adresini gösteriyor ve isteğe bağlı olarak profil tablosundan ek bilgiler çekiyoruz.

Kimlik Doğrulama Akışı Örneği (Giriş/Çıkış)

Giriş ve çıkış işlemleri genellikle istemci tarafı etkileşimleri gerektirse de, Next.js Server Actions ve Supabase'in çerez yönetimi sayesinde bu işlemleri güvenli bir şekilde gerçekleştirebiliriz.

// app/login/page.tsx (Örnek giriş sayfası)
import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'

export default function LoginPage() {
  async function signIn(formData: FormData) {
    'use server'
    const email = formData.get('email') as string
    const password = formData.get('password') as string
    const supabase = createClient()

    const { error } = await supabase.auth.signInWithPassword({
      email,
      password,
    })

    if (error) {
      console.error('Giriş hatası:', error.message)
      // Hata mesajını kullanıcıya göstermek için daha gelişmiş bir yöntem kullanılabilir.
      redirect('/login?message=Giriş başarısız oldu.')
    } else {
      redirect('/dashboard') // Başarılı giriş sonrası dashboard'a yönlendir
    }
  }

  async function signOut() {
    'use server'
    const supabase = createClient()
    await supabase.auth.signOut()
    redirect('/login')
  }

  return (
    

Giriş Yap

Çıkış Yap

) }

Bu örnek, signIn ve signOut Server Actions'larını kullanarak giriş ve çıkış işlemlerini nasıl yöneteceğimizi gösterir. Supabase, başarılı bir giriş sonrası oturum çerezlerini otomatik olarak ayarlar ve signOut çağrıldığında bu çerezleri temizler.

Hata Yönetimi ve Güvenlik İpuçları

Hata Yakalama ve Kullanıcıya Bildirme

Uygulamanızın sağlamlığı için Supabase işlemlerinden dönen hataları düzgün bir şekilde yönetmek çok önemlidir. Hataları yakalamak ve kullanıcıya anlaşılır geri bildirimler sunmak, uygulamanızın güvenilirliğini artırır.

  • Konsol Logları: Geliştirme aşamasında hataları konsola yazdırmak (console.error) sorunun kök nedenini anlamak için faydalıdır.
  • Kullanıcı Arayüzü Geri Bildirimi: Üretim ortamında, kullanıcıya "Bir şeyler yanlış gitti, lütfen tekrar deneyin" gibi genel bir hata mesajı göstermek daha iyidir. Hassas hata detaylarını doğrudan kullanıcıya göstermekten kaçının.
  • Hata İzleme Araçları: Sentry veya Bugsnag gibi hata izleme araçlarını entegre ederek sunucu tarafında oluşan hataları otomatik olarak takip edebilirsiniz.

Row-Level Security (RLS) Kullanımı

Supabase'in en güçlü güvenlik özelliklerinden biri Row-Level Security (RLS)'dir. RLS, veritabanı seviyesinde, belirli bir kullanıcının hangi verilere erişebileceğini veya hangi verileri değiştirebileceğini tanımlamanıza olanak tanır.

Örneğin, bir todos tablosunda, her kullanıcının yalnızca kendi oluşturduğu görevleri görmesini sağlayabilirsiniz:

  1. Supabase panelinizde todos tablosuna gidin.
  2. "Policies" sekmesine
Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.