feat: admin paneli + blog + testimonials + SEO yöneticisi

Backend altyapısı:
- 4 yeni Appwrite tablosu: blog_posts, testimonials, seo_pages, seo_settings
- Appwrite Storage bucket: kovak-yazilim-media (görsel yüklemeleri)
- Appwrite Auth ile session cookie tabanlı koruma

Admin paneli (/admin):
- Login akışı (email/password) + protected layout
- Dashboard: sayım kartları + hızlı aksiyonlar
- Blog CRUD: markdown content, kapak görseli, draft/published, SEO alanları
- Services CRUD: lucide ikon seçici
- Projects CRUD: teknoloji etiketleri, live URL
- Testimonials CRUD: puanlama
- SEO yöneticisi: global ayarlar + sayfa bazlı override
- Mesaj inbox: status filtreleme + güncelleme
- Medya kütüphanesi: Appwrite Storage upload/delete

Public:
- /blog ve /blog/[slug] sayfaları (markdown render)
- Anasayfaya Testimonials bölümü
- Tüm public sayfalarda generateMetadata + seo_pages override
- Header'a Blog linki

Route yapısı:
- app/(site)/ — public site, Header/Footer ortak
- app/admin/login — auth dışı
- app/admin/(protected)/ — requireUser() korumalı

23 route üretiliyor, public static, admin dynamic.
This commit is contained in:
Ege Can Komur
2026-05-20 02:13:09 +03:00
parent 0f20309e4d
commit f833d429fc
52 changed files with 2999 additions and 81 deletions
+93 -31
View File
@@ -1,13 +1,14 @@
# Kovak Yazılım — Kurumsal Web Sitesi
# Kovak Yazılım — Kurumsal Site + Admin Panel
Next.js 16 + TypeScript + Tailwind v4 + Appwrite ile geliştirilmiş kurumsal site.
Next.js 16 + TypeScript + Tailwind v4 + Appwrite ile geliştirilmiş kurumsal site ve içerik yönetim paneli.
## Teknoloji
- **Framework:** Next.js 16 (App Router, Turbopack, React 19)
- **Stil:** Tailwind CSS v4
- **Backend:** Appwrite (TablesDB) — `https://db.kovaksoft.com`
- **İkonlar:** lucide-react + inline SVG brand icons
- **Backend:** Appwrite (TablesDB + Storage + Auth) — `https://db.kovaksoft.com`
- **İçerik:** Markdown (marked.js)
- **İkonlar:** lucide-react + inline SVG
- **Form:** React Server Actions + `useActionState`
## Kurulum
@@ -15,59 +16,120 @@ Next.js 16 + TypeScript + Tailwind v4 + Appwrite ile geliştirilmiş kurumsal si
```bash
npm install
cp .env.example .env.local
# .env.local dosyasındaki APPWRITE_API_KEY'i Appwrite Console'dan oluşturup ekle
# .env.local içine APPWRITE_API_KEY'i Appwrite Console'dan oluşturup ekle
npm run dev
```
Site: <http://localhost:3000>
Admin: <http://localhost:3000/admin/login>
## İlk Admin Kullanıcısı
1. Appwrite Console → Auth → Users → Create User
2. Email + şifre belirle
3. `/admin/login` üzerinden giriş yap
## Appwrite Yapılandırması
**Project ID:** `69f27b51000a5bee46ce`
**Database ID:** `kovak-yazilim-db`
**Bucket ID:** `kovak-yazilim-media`
### Tablolar
| Tablo | İçerik | Yazma izni |
|---|---|---|
| `services` | Hizmetler (slug, title, description, icon, order, featured) | yalnız users |
| `projects` | Referans projeler (slug, title, description, image_url, live_url, category, technologies[], year, featured) | yalnız users |
| `contact_messages` | İletişim formu kayıtları (name, email, phone, subject, message, status) | herkes create, users read/update/delete |
| Tablo | İçerik |
|---|---|
| `services` | Hizmet kartları (slug, title, description, icon, order, featured) |
| `projects` | Referans projeler (slug, title, description, image_url, live_url, category, technologies[], year, featured) |
| `blog_posts` | Blog yazıları (slug, title, excerpt, content, cover_image, author, status, published_at, tags[], seo_*) |
| `testimonials` | Müşteri yorumları (name, role, company, message, rating, image_url, order, featured) |
| `seo_pages` | Sayfa bazlı SEO override (path, title, description, og_image, canonical, noindex) |
| `seo_settings` | Global SEO ayarları (singleton — rowId: `global`) |
| `contact_messages` | İletişim formu kayıtları (anonim create, users read/update/delete) |
`contact_messages.create` izni `any` — anonim kullanıcılar form gönderebilsin diye.
Diğer tüm yazma işlemleri yetkili kullanıcı (admin) gerektirir.
### Storage
### API Key Oluşturma
`kovak-yazilim-media` — 10 MB max, image-only (jpg/png/webp/gif/svg/avif). Public read.
1. Appwrite Console → Settings → API Keys → Create
2. Scopes: `databases.read`, `tables.read`, `rows.read`, `rows.write`
3. `.env.local` içine `APPWRITE_API_KEY=` olarak yapıştır
### API Key
Appwrite Console → Settings → API Keys → Create
Scopes: `databases.read`, `tables.read`, `rows.read`, `rows.write`, `files.read`, `files.write`, `users.read`
## Admin Paneli
`/admin` altında:
- **Pano** (`/admin`) — Sayım kartları + hızlı aksiyonlar
- **Blog** (`/admin/blog`) — Yazı CRUD, draft/published durumu, markdown editor
- **Hizmetler** (`/admin/hizmetler`) — Hizmet CRUD, lucide ikon seçici
- **Projeler** (`/admin/projeler`) — Portfolyo CRUD
- **Referanslar** (`/admin/referanslar`) — Müşteri yorumları
- **SEO** (`/admin/seo`) — Global meta + sayfa bazlı override
- **Mesajlar** (`/admin/iletisim`) — Form inbox, status (new/read/replied/archived)
- **Medya** (`/admin/medya`) — Appwrite Storage browser, upload/delete
### Auth Akışı
`lib/auth.ts``getCurrentUser()` & `requireUser()`
Login → `account.createEmailPasswordSession` → session secret HTTP-only cookie (`kovak_session`)
Admin layout (`app/admin/(protected)/layout.tsx`) `requireUser()` çağrısı yapar — yetkisiz giriş `/admin/login`'e redirect.
## SEO Sistemi
`lib/seo.ts``buildMetadata(path, fallback)`
Sıralama (override öncelikli):
1. `seo_pages` tablosunda o path için kayıt varsa → onun title/description/og_image kullanılır
2. Yoksa sayfanın kendi fallback `Metadata` objesi
3. O da yoksa `seo_settings` (global)
4. O da yoksa `lib/site-config.ts`
## Yapı
```
app/
actions.ts # Server Action: submitContact
layout.tsx # Root layout + Header/Footer
page.tsx # Anasayfa
hizmetler/ # /hizmetler
projeler/ # /projeler
hakkimizda/ # /hakkimizda
iletisim/ # /iletisim
components/ # Header, Footer, Hero, ContactForm, …
(site)/ # Public site (Header + Footer ortak)
page.tsx # Anasayfa
hizmetler/ # /hizmetler
projeler/ # /projeler
blog/ # /blog, /blog/[slug]
hakkimizda/
iletisim/
admin/
login/ # /admin/login (auth dışı)
(protected)/ # requireUser() ile korunan grup
page.tsx # /admin
blog/
hizmetler/
projeler/
referanslar/
seo/
iletisim/
medya/
actions.ts # Public Server Action: submitContact
layout.tsx # Root layout (html/body)
components/
admin/ # Sidebar, topbar, form helpers, delete button
header.tsx, footer.tsx
hero.tsx, services-grid.tsx, projects-grid.tsx, testimonials.tsx
contact-form.tsx
lib/
appwrite.ts # Browser client
appwrite-server.ts # Server client (uses APPWRITE_API_KEY)
data.ts # listServices / listProjects (Server-only)
site-config.ts # Marka, iletişim, fallback hizmetler
types.ts
public/logo.png # Logo (kovakyazilim.com'dan)
appwrite.ts # Browser client
appwrite-server.ts # adminClient (API key) + sessionClient (cookie)
auth.ts # Session helpers
admin-actions.ts # Tüm CRUD server actions (gate() ile auth check)
data.ts # listX / getX sorguları
seo.ts # buildMetadata
site-config.ts # Marka + fallback değerler
types.ts # Row tipleri
public/logo.png # Logo
```
## Build
```bash
npm run build
npm run build # 23 route, public sayfalar static, admin dynamic
npm start
```