Anasayfada en alttaki 'Projenizi konuşalım' CTA section'ı koyu navy ile bitiyor, footer da navy. Aradaki 96px beyaz alan görsel kopukluk yaratıyordu. Diğer sayfalarda da son section'lar zaten kendi alt padding'ini veriyor (py-20), ekstra footer margin'i gereksiz.
Kovak Yazılım — Kurumsal Site + Admin Panel
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 + Storage + Auth) —
https://db.kovaksoft.com - İçerik: Markdown (marked.js)
- İkonlar: lucide-react + inline SVG
- Form: React Server Actions +
useActionState
Kurulum
npm install
cp .env.example .env.local
# .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ı
- Appwrite Console → Auth → Users → Create User
- Email + şifre belirle
/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 |
|---|---|
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) |
Storage
kovak-yazilim-media — 10 MB max, image-only (jpg/png/webp/gif/svg/avif). Public read.
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):
seo_pagestablosunda o path için kayıt varsa → onun title/description/og_image kullanılır- Yoksa sayfanın kendi fallback
Metadataobjesi - O da yoksa
seo_settings(global) - O da yoksa
lib/site-config.ts
Yapı
app/
(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 # 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
npm run build # 23 route, public sayfalar static, admin dynamic
npm start
Gitea Remote
git remote add origin ssh://git@git.kovaksoft.com:2222/kovakmedya/kovakyazilim.git
git push -u origin main