ArMenu
Çok kiracılı QR menüler, tarayıcı içinde AR — kurulacak uygulama yok.

- Rolüm
- Tek geliştirici — API, her iki React uygulaması, 3B varlık hattı, dağıtım ve gözlemlenebilirlik.
- Durum
- Canlı
Problem
Basılı bir menü, misafire yemeğin neye benzediğini gösteremez, onun dilinde okunamaz ve yeniden bastırılmadan değiştirilemez. Buna verilen her dijital cevap misafirden bir şey kurmasını ister; restoran masasında fikrin öldüğü yer de tam olarak orasıdır.
Ne yaptım
Çok kiracılı bir B2B SaaS. Misafir masadaki QR kodu okutuyor, menüyü kendi dilinde okuyor ve model-viewer üzerinden yemeği artırılmış gerçeklikle masaya koyuyor — hem de zaten açık olan tarayıcısında. Arkasında: PostgreSQL üzerinde bir .NET 10 API ve yüklenen 3B modeli optimize edilmiş GLB, USDZ ve poster görsellerine dönüştüren ayrı bir Node servisi.
Nasıl görünüyor

Masadaki QR kodu okuttuktan sonra misafirin gördüğü ekran. 
3B yığını yalnızca modeli olan bir yemek açıldığında yükleniyor — AR'ı hiç kullanmayan misafirler bedelini hiç ödemiyor. 
Panelden basılan masa başına QR kartları — masa numarası okutmayla birlikte geliyor.
Mimari
Misafir ve panel uygulamaları
CDN üzerinde iki statik uygulama. Misafir uygulamasının mobil veride anında açılması gerekiyor; panel ise işletme sahiplerinin kendi menülerini düzenlediği yer.
- React 19
- TanStack Router + Query
- Vite
- React Aria
API
Her kural tek bir yerde; istemcilerin TypeScript tiplerini ürettiği, depoya işlenmiş bir OpenAPI sözleşmesinin arkasında.
- .NET 10
- Minimal APIs
- CQRS
- JWT per tenant
Kalıcılık
Kiracı izolasyonunu filtrelemeyi hatırlamak değil, veritabanının kendisi zorunlu kılıyor.
- PostgreSQL 18
- EF Core 10
- Row-level security
Varlık hattı
Yüklenen modeli Meshopt + WebP GLB'ye, iOS Quick Look için USDZ'ye ve poster görsellerine dönüştürüyor.
- Node.js
- glTF Transform
- meshoptimizer
- headless Chrome
Kararlar ve ödünleşmeler
Satır düzeyi güvenlik sorgu katmanında değil, veritabanında
Uygulama kodunda yaşayan bir kiracı filtresi, bir restorana başka bir restoranın menüsünü göstermekten yalnızca bir unutulmuş WHERE uzaktır. İzolasyonu Postgres'e itmek sızıntıyı düşük ihtimalli değil, imkânsız yapıyor.
Temiz mimariyi disiplin değil, bir test zorunlu kılıyor
Bir kaynak bağımlılığı dışarı baktığı anda mimari testler derlemeyi düşürüyor. Yalnızca README'de yazan bir katman kuralı, aşınan bir katman kuralıdır.
Native uygulama yerine WebAR
Masada duran bir müşteri, menüye bakmak için uygulama kurmaz. model-viewer talep üzerine yükleniyor; böylece AR'ı hiç açmayan misafirler onun bedelini hiç ödemiyor.
3B varlıklar için ayrı bir servis
Mesh optimizasyonu yavaş ve CPU'ya bağlı bir iş. Onu API'nin dışında tutmak, tek bir büyük yüklemenin bir menü isteğini arkasında bekletmesini imkânsız kılıyor.
Sonuç
Restoranlar kendi menülerini değiştiriyor; misafirler sipariş vermeden önce yemeği görüyor. İki taraf da hiçbir şey kurmuyor.
Ölçülen
- Lighthouse (perf / erişilebilirlik / en iyi uygulama / SEO)
- 98 / 100 / 100 / 100
- Toplam bloklama süresi · düzen kayması
- 0 ms · 0
- Başlangıç JavaScript'i (gzip)
- 117 KiB
- Talep üzerine yüklenen 3B yığını (gzip)
- 291 KiB