99 Commits
Author SHA1 Message Date
AyrisAI 5122ec24fc fix: revert to stable Next.js 15 and add @swc/helpers to dependencies for Docker standalone runtime 2026-08-20 17:24:40 +03:00
AyrisAI b950a31e3b fix: move @import rule to top of globals.css to satisfy PostCSS specification 2026-08-20 17:20:22 +03:00
AyrisAI f2b2537cd0 chore: upgrade Next.js to latest in web app 2026-08-20 17:15:42 +03:00
AyrisAI 484c7ce113 fix: resolve TypeScript type mismatch error in fetchRestaurantBySlug 2026-08-20 17:12:32 +03:00
AyrisAI 067d65940f fix: fallback to basic select query when cover_url column is not present on production database 2026-08-20 17:10:19 +03:00
AyrisAI b7e128fb8c fix: resolve slug fallback rendering for demo/gusto-brasserie and add root [slug] routing 2026-08-20 17:05:45 +03:00
AyrisAI 6055130828 docs: record EAS env var and entitlement identifier bugs 2026-08-20 16:16:14 +03:00
AyrisAI bb4cd1b0fc fix(mobile): stop matching entitlement by hardcoded identifier string
RevenueCat's entitlement identifier contains U+2024 (ONE DOT LEADER),
not a plain period — "Menul.io Pro" never matched the real
"Menul⁚io Pro" key, so isProActive() stayed false even after a real
purchase (confirmed via a genuine sandbox trial that RevenueCat
recorded as active while the app kept showing "Ücretsiz plan").
RevenueCat's API doesn't allow renaming an entitlement's lookup_key
after creation (405), so fixed on our side instead: this app only
ever grants one entitlement, so "any active entitlement" == Pro,
no identifier string needed.
2026-08-20 16:15:44 +03:00
AyrisAI 102cc0781e fix(mobile): add missing RevenueCat key to EAS production build env
eas.json's production build profile hardcodes its own env block —
local apps/mobile/.env is never read by EAS cloud builds. The
RevenueCat public key was missing from that list, so every
production/TestFlight build compiled EXPO_PUBLIC_REVENUECAT_API_KEY
as undefined, making configurePurchases() silently no-op and every
later Purchases call throw "no singleton instance".
2026-08-20 15:57:40 +03:00
AyrisAI 0836fc8539 feat: redesign web menu layout, add header cover banner & dynamic header layout, refine mobile inputs and theme selector 2026-08-20 15:07:13 +03:00
AyrisAI 6fb91c94ff fix(mobile): configure Purchases on menu editor load
"There is no singleton instance" when tapping Yayınla — the app can
land directly on /menu (e.g. iOS restoring the last screen on
relaunch) without ever running index.tsx's routing gate, so
Purchases.configure() was never called. Menu editor's load() now
configures it defensively too, same pattern as account/subscription.tsx.
2026-08-20 13:52:17 +03:00
AyrisAI 67cd5a488c fix(mobile): fix unreachable back button on subscription screen
Missing safe-area top inset pushed the header (back arrow + title)
up under the status bar/notch, overlapping the clock and making the
button effectively untappable. Also falls back to router.replace
when there's no back history instead of silently no-op'ing.
2026-08-20 13:33:24 +03:00
AyrisAI 55bb415e82 docs: record trial + publish-gating integration 2026-08-20 13:24:16 +03:00
AyrisAI d87f66efff feat(mobile): gate publish behind subscription, surface free trial
Publishing (including re-publishing after a lapsed subscription —
PRD §15) now checks Pro entitlement first; if inactive, prompts the
owner to the paywall instead of calling the publish endpoint. The
paywall also flags packages with an active introductory offer as
"7 gün ücretsiz dene" (both plans now have a 7-day free trial
configured in App Store Connect, Turkey territory).
2026-08-20 13:23:55 +03:00
AyrisAI 5a0c1ddc82 docs: record RevenueCat mobile SDK integration 2026-08-20 13:21:22 +03:00
AyrisAI b25c742eea feat(mobile): integrate react-native-purchases (RevenueCat)
- Purchases.configure() runs with appUserID = restaurantId at every
  point the id becomes known (login resolve, cold-start rehydration,
  onboarding restaurant creation) — this must match what the backend
  webhook expects (see apps/api/src/routes/subscription.ts).
- New account/subscription.tsx paywall: current entitlement status,
  offering packages with real store prices, purchase, restore.
- Linked from the account screen.

Native module — requires an EAS/dev-client build, not plain Expo Go.
2026-08-20 13:20:54 +03:00
AyrisAI 3509388c37 docs: record App Store Connect and RevenueCat setup 2026-08-20 13:13:38 +03:00
AyrisAI c85d3864fc feat(subscription): implement RevenueCat webhook handler
Verifies the shared-secret Authorization header, then maps
RevenueCat's app_user_id (the restaurant id — mobile must configure
Purchases with appUserID: restaurantId) to an upsert into
subscriptions. INITIAL_PURCHASE/RENEWAL/PRODUCT_CHANGE/UNCANCELLATION
-> active, BILLING_ISSUE -> grace_period, EXPIRATION -> suspended.
CANCELLATION alone does not suspend — it only means auto-renew is
off, access continues until the period actually expires.

Tested end-to-end against the real Supabase project (create
restaurant, POST the webhook, verify the subscriptions row).
2026-08-20 13:13:02 +03:00
AyrisAI a719d41776 feat(web): add privacy policy and support pages for App Store listing 2026-08-20 12:24:30 +03:00
AyrisAI 6cc56a198a perf(ai-scanner): drop confidence scoring to simplify AI menu import
Removes the per-item confidence field end to end (prompt, extraction
parsing, ai_import_items writes, API responses, low-confidence badge
in the mobile review screen). ai_import_items.confidence column is
left in place but unused (nullable, no destructive migration).
2026-08-20 05:47:55 +03:00
AyrisAI 7b9cfb6858 feat(api): automate custom domain setup via Cloudflare + Coolify
Adding a custom domain now:
- creates a Cloudflare Custom Hostname (SSL for SaaS) automatically,
  returning the ownership + SSL validation TXT records to show the
  restaurant owner alongside the CNAME instruction
- adds the domain to the Coolify app's fqdn and triggers a restart
  (Coolify only regenerates Traefik labels on deploy, not on a bare
  fqdn PATCH — coollabsio/coolify#6281)
- /verify now checks Cloudflare's actual ssl.status instead of doing
  a DNS CNAME lookup, which is structurally blind on proxied hostnames

Tested end-to-end against the real Cloudflare zone and Coolify app
(create, verify data, then clean up) before this push — see
docs/PROGRESS.md.

Requires CLOUDFLARE_API_TOKEN, CLOUDFLARE_ZONE_ID, COOLIFY_API_TOKEN,
COOLIFY_BASE_URL, COOLIFY_WEB_APP_UUID in the API's environment.
Without them, domain add/verify falls back to DB-only bookkeeping.
2026-08-20 05:43:40 +03:00
AyrisAI bb27c3f773 docs: record today's production infra findings and fixes 2026-08-20 05:26:34 +03:00
AyrisAI e0581440cb fix(api): don't undo domain verification on DNS re-check, fix theme lookup crash
- domains.ts: a proxied Cloudflare custom hostname's real CNAME target
  is never visible to a plain DNS lookup, so a re-verify always fails
  and was silently downgrading already-verified domains back to
  pending. Only a first-time check can now land on pending.
- restaurants.ts: PUT /restaurants/:id/theme referenced an undeclared
  themeData variable (pre-existing tsc error on main, not introduced
  here) — added the missing themes-by-key lookup it depended on.
2026-08-20 05:25:50 +03:00
AyrisAI 77eecd53ac fix(web): strip trailing slash from wildcard/custom-domain rewrite target
Root-path requests to a subdomain or custom domain rewrote to
/menu/<slug>/ (trailing slash), which the [slug] dynamic route can't
match — the app fell through to notFound() even for verified,
published restaurants. Custom domains (e.g. ad.ayris.tech) always hit
this since their only real traffic is the root path.
2026-08-20 05:18:59 +03:00
AyrisAI 1a3e46f16c fix(api): raise Fastify body size limit for AI menu photo uploads
Default 1 MiB limit rejected base64-encoded camera photos before the
request handler ever ran ("Request body is too large"), unrelated to
the OpenAI model. Also adds the public domains RLS policy needed for
custom-domain resolution on the public menu page (already applied
manually via SQL Editor, committing for history).
2026-08-20 05:13:03 +03:00
AyrisAI 93b2a77127 fix(mobile): update public menu URL format to https://menul.io/menu/:slug 2026-08-20 04:32:25 +03:00
AyrisAI c6b15ffa52 fix(mobile): install missing expo-linking and align native dependencies to 100% Expo SDK 52 2026-08-20 04:09:25 +03:00
AyrisAI c0544251b8 feat(themes): add Eleia Coastal Kitchen Mediterranean Aegean design system 2026-08-20 03:46:41 +03:00
AyrisAI bf637b02ed feat(themes): add Neon Street Fuze graffiti burger/taco menu design system 2026-08-20 03:44:02 +03:00
AyrisAI 809200550e feat(themes): add La Maison d'Élève French luxury editorial restaurant design system 2026-08-20 03:41:07 +03:00
AyrisAI de8bd506b8 feat(themes): add Swiss Brutalist restaurant design system with chapter numbers and high-contrast grid 2026-08-20 03:35:44 +03:00
AyrisAI 83fa4236ea fix(mobile): disable experimental newArchEnabled to prevent TurboModule SIGABRT crash 2026-08-20 03:10:48 +03:00
AyrisAI 4e65d3f708 feat(web): make category navigation and section headers sticky with frosted glass effect 2026-08-20 02:59:24 +03:00
AyrisAI 89c2f62995 feat(themes): add Amber Artisan 2-column bento gourmet dark theme 2026-08-20 02:56:38 +03:00
AyrisAI da3d4d291b chore(assets): ensure 1024x1024 app icon is flattened without alpha for Apple App Store compliance 2026-08-20 02:45:19 +03:00
AyrisAI 32818766f0 fix(mobile): remove custom font loader causing SIGABRT crash on iOS release 2026-08-20 02:43:22 +03:00
AyrisAI 3257f7fe57 security: remove any hardcoded credentials from codebase 2026-08-20 02:39:21 +03:00
AyrisAI f5eebed0a7 fix(mobile): add hardcoded production env fallbacks to prevent launch crash 2026-08-20 02:38:37 +03:00
AyrisAI 856347cabd fix(api): add GET / root healthcheck endpoint for Coolify 2026-08-20 02:31:04 +03:00
AyrisAI 1379642832 chore: add type module to root package.json 2026-08-20 02:26:57 +03:00
AyrisAI 373de65d07 fix(docker): add curl and healthcheck routes for Coolify 2026-08-20 02:26:21 +03:00
AyrisAI 4f4f68b924 chore(eas): set ios build image to latest 2026-08-20 02:18:37 +03:00
AyrisAI 31ace73a09 chore(api): set production default port to 3000 2026-08-20 02:16:48 +03:00
AyrisAI e56f92bf56 fix(api): bundle with tsup to resolve ESM shared module execution 2026-08-20 02:16:07 +03:00
AyrisAI bace019314 fix(docker): ensure public directory exists for web standalone build 2026-08-20 02:10:07 +03:00
AyrisAI 660c38e5e2 fix: add expo-asset and expo-constants to mobile dependencies 2026-08-20 02:09:23 +03:00
AyrisAI 6843c153ef fix(docker): copy tsconfig.base.json in Dockerfiles 2026-08-20 01:58:57 +03:00
AyrisAI 437af0b251 fix: eas config and dockerfiles 2026-08-20 01:53:41 +03:00
AyrisAI 97b83c7fd4 first commit 2026-08-20 01:51:59 +03:00