Add QR menu design spec and update gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
0beefdee7f
commit
f879d65cfc
@@ -39,3 +39,6 @@ yarn-error.log*
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# brainstorming sessions
|
||||
.superpowers/
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
# Kozmos Beach & More — QR Menü Sitesi Tasarım Dokümanı
|
||||
|
||||
**Tarih:** 2026-06-03
|
||||
**Proje:** kozmosqr
|
||||
**Stack:** Next.js 16.2.7 · React 19.2 · Tailwind CSS v4 · TypeScript
|
||||
|
||||
---
|
||||
|
||||
## Amaç
|
||||
|
||||
Masa başında QR okutulunca açılan, uygulama gerektirmeyen, sadece görüntüleme amaçlı dijital menü. TR/EN dil desteği, mobil-first, PWA-ready.
|
||||
|
||||
---
|
||||
|
||||
## Tasarım Kararları (Brainstorming Özeti)
|
||||
|
||||
| Karar | Seçim | Gerekçe |
|
||||
|---|---|---|
|
||||
| Ürün kartı stili | Minimal liste (emoji + isim + açıklama + fiyat) | Hızlı taranır, fotoğraf zorunluluğu yok |
|
||||
| Kategori navigasyon | Sticky alt tab bar | Başparmakla kolay erişim, native his |
|
||||
| i18n yaklaşımı | URL tabanlı (`/tr`, `/en`) | Next.js native `[lang]` dynamic segment |
|
||||
| Günün Önerisi / Rakı Gecesi | Sonraki sprint'e bırakıldı | Şimdilik kapsam dışı |
|
||||
|
||||
---
|
||||
|
||||
## Tasarım Dili
|
||||
|
||||
- **Renkler:** krem `#F5F0E8` · bej `#E8DCC8` · turkuaz `#4AAFA8` · yeşil `#5C8A5C` · koyu kahve `#3D2B1F`
|
||||
- **Font:** Playfair Display (başlıklar, italic vurgu) + Inter (gövde, fiyat, etiketler)
|
||||
- **His:** Bohem, Ege, hasır doku — Magic UI animasyon kalitesi ile desteklenmiş
|
||||
- **Animasyon:** Minimal — scroll geçişleri, tab değiştirme fade
|
||||
|
||||
---
|
||||
|
||||
## Sayfa Yapısı
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ KOZMOS Beach&More │ sticky header — bg: #3D2B1F
|
||||
│ TR EN│ dil seçici sağ üst
|
||||
├─────────────────────┤
|
||||
│ │
|
||||
│ [Aktif kategori │ scroll area — bg: #F5F0E8
|
||||
│ içeriği] │
|
||||
│ │
|
||||
│ 🥗 Akdeniz Salatası│ minimal liste satırı
|
||||
│ Taze sebzeler ₺120 │
|
||||
│ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
|
||||
│ │
|
||||
│ [WA btn] │ fixed, sağ alt, bg: #25D366
|
||||
├─────────────────────┤
|
||||
│ 🥗 🍽️ 🍕 🍹 🍮│ sticky bottom tab bar — bg: #3D2B1F
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dosya Yapısı
|
||||
|
||||
```
|
||||
app/
|
||||
[lang]/
|
||||
layout.tsx — font yükleme, html lang attr, meta tags
|
||||
page.tsx — menü sayfası (Server Component)
|
||||
manifest.ts — PWA web app manifest
|
||||
proxy.ts — / → /tr yönlendirmesi (Next.js 16 proxy)
|
||||
data/
|
||||
menu.ts — tüm menü verisi (TR+EN, tip tanımlı)
|
||||
dictionaries/
|
||||
tr.json — UI string'leri Türkçe
|
||||
en.json — UI string'leri İngilizce
|
||||
public/
|
||||
icons/ — PWA icon'ları (192x192, 512x512)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Veri Modeli
|
||||
|
||||
```ts
|
||||
// data/menu.ts
|
||||
|
||||
type LocalizedString = { tr: string; en: string }
|
||||
|
||||
type MenuItem = {
|
||||
id: string
|
||||
emoji: string
|
||||
name: LocalizedString
|
||||
description: LocalizedString
|
||||
price: number // TL
|
||||
highlight?: boolean // Günün Önerisi — sonraya hazır alan
|
||||
}
|
||||
|
||||
type Category = {
|
||||
id: string
|
||||
emoji: string
|
||||
label: LocalizedString
|
||||
items: MenuItem[]
|
||||
}
|
||||
|
||||
export const categories: Category[] = [ ... ]
|
||||
```
|
||||
|
||||
**Kategoriler (6):** Başlangıçlar · Ana Yemekler · Pizzalar · Mezeler · İçecekler · Tatlılar
|
||||
**Her kategoride:** 4–5 ürün, TR+EN isim ve açıklama
|
||||
|
||||
---
|
||||
|
||||
## i18n Mimarisi
|
||||
|
||||
**Routing:** `app/[lang]/page.tsx` — `/tr` ve `/en` URL'leri
|
||||
|
||||
**proxy.ts:**
|
||||
- `/` → `/tr` yönlendirir (varsayılan locale)
|
||||
- Desteklenmeyen locale → 404
|
||||
|
||||
**dictionaries/tr.json + en.json:**
|
||||
```json
|
||||
{
|
||||
"nav": { "starters": "Başlangıçlar", "mains": "Ana Yemekler", ... },
|
||||
"whatsapp": "Rezervasyon için yazın",
|
||||
"currency": "₺"
|
||||
}
|
||||
```
|
||||
|
||||
**getDictionary (server-only):** `app/[lang]/dictionaries.ts`
|
||||
- `import 'server-only'` ile client bundle'dan korunur
|
||||
- `hasLocale()` ile geçersiz locale → `notFound()`
|
||||
|
||||
**Params:** Next.js 16 gereği `await params` — senkron erişim yok.
|
||||
|
||||
---
|
||||
|
||||
## Bileşen Mimarisi
|
||||
|
||||
Bileşenler varsayılan olarak Server Component'tir. `'use client'` yalnızca aktif tab detection için gereklidir.
|
||||
|
||||
```
|
||||
app/[lang]/page.tsx
|
||||
└─ <MenuPage lang dict categories /> — Server Component
|
||||
├─ <Header lang /> — Server Component, dil linkleri
|
||||
├─ <CategorySection id="starters" ...> — Server Component, her kategori için
|
||||
│ └─ <MenuItemRow> — Server Component
|
||||
├─ <WhatsAppButton phone /> — Server Component (statik link)
|
||||
└─ <BottomTabBar categories /> — CLIENT Component ⚠️
|
||||
```
|
||||
|
||||
**BottomTabBar neden client?**
|
||||
Sayfa tek scroll alanı, tüm kategoriler alt alta sıralı. Tab'lar `href="#category-id"` anchor linkleri. Aktif tab'ı belirlemek için Intersection Observer kullanılır — bu `useEffect` + `useState` gerektirir.
|
||||
|
||||
**Sayfada sadece bu bir bileşen `'use client'` alır.**
|
||||
|
||||
---
|
||||
|
||||
## PWA
|
||||
|
||||
`app/manifest.ts`:
|
||||
```ts
|
||||
{ name: 'Kozmos Beach & More', short_name: 'Kozmos',
|
||||
start_url: '/tr', display: 'standalone',
|
||||
background_color: '#F5F0E8', theme_color: '#3D2B1F' }
|
||||
```
|
||||
|
||||
`app/[lang]/layout.tsx` meta tags:
|
||||
- `viewport` + `theme-color`
|
||||
- `apple-mobile-web-app-capable`
|
||||
|
||||
---
|
||||
|
||||
## Tailwind v4 Yapılandırması
|
||||
|
||||
`app/globals.css` içinde `@theme inline` ile özel renkler:
|
||||
```css
|
||||
@import "tailwindcss";
|
||||
|
||||
@theme inline {
|
||||
--color-cream: #F5F0E8;
|
||||
--color-beige: #E8DCC8;
|
||||
--color-teal: #4AAFA8;
|
||||
--color-green: #5C8A5C;
|
||||
--color-coffee: #3D2B1F;
|
||||
--font-display: 'Playfair Display', serif;
|
||||
--font-body: 'Inter', sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## WhatsApp Butonu
|
||||
|
||||
Fixed, sağ alt köşe. `href="https://wa.me/90XXXXXXXXXX"` — telefon numarası `data/menu.ts`'ten gelir, hardcode edilmez.
|
||||
|
||||
---
|
||||
|
||||
## Kapsam Dışı (Sonraki Sprint)
|
||||
|
||||
- Günün Önerisi özel kartı
|
||||
- Perşembe Rakı Gecesi banner'ı
|
||||
- Gerçek ürün fotoğrafları (Next.js Image optimizasyonu)
|
||||
- Admin paneli / menü düzenleme arayüzü
|
||||
Reference in New Issue
Block a user