Commit Graph
86 Commits
Author SHA1 Message Date
AyrisAI 2530ab4005 feat(mobile): add multiline text with Enter, per-text independent font selection and font size controls 2026-08-21 00:55:44 +03:00
AyrisAI b72846bd91 feat(mobile): integrate QrTemplate5 with 5.png background image and dynamic texts 2026-08-21 00:52:26 +03:00
AyrisAI d2846ed628 feat(mobile): add QrTemplate4 Crimson Petal, support full Turkish characters on all system fonts and templates 2026-08-21 00:41:16 +03:00
AyrisAI 4dbb68a73a feat(mobile): add full text editing, show/hide switches and font family selector for QR stands 2026-08-21 00:36:14 +03:00
AyrisAI 932c174b5f fix(mobile): resolve TSpan text overlapping in QrTemplate3 2026-08-21 00:31:17 +03:00
AyrisAI 34dd24eee2 feat(mobile): register QrTemplate2 Daily Grind and filter UI to active component templates 2026-08-21 00:30:14 +03:00
AyrisAI 8481a34e61 feat(mobile): add QrTemplate3 Pizzeria, fix PDF export for component system 2026-08-21 00:25:44 +03:00
AyrisAI ccd8c90267 fix(mobile): decode XML entities for react-native-svg text rendering 2026-08-21 00:07:43 +03:00
AyrisAI 3629f98855 fix(mobile): proper nested-g depth counting for qr-placeholder replacement 2026-08-21 00:06:03 +03:00
AyrisAI dd282f3987 fix(mobile): strip XML comments before SvgXml parse to fix closing tag error 2026-08-21 00:02:37 +03:00
AyrisAI 4236ddb5ee feat: re-integrate all SVGs from svg ornekleri/ fresh, add qr-6 2026-08-20 23:59:45 +03:00
AyrisAI c7e4832441 fix(mobile): do not mutate SVG attributes, only replace qr-placeholder group 2026-08-20 23:58:21 +03:00
AyrisAI fa50e73198 fix(mobile): inject QR directly into SVG XML for pixel-perfect placement 2026-08-20 23:56:37 +03:00
AyrisAI 808097377d feat(qr-stands): add qr-5 L'Atelier Bistro Fine Dining template 2026-08-20 23:50:30 +03:00
AyrisAI 6cde8dfb87 feat: sync qr presets and mobile rendering with svg/ directory 2026-08-20 23:43:58 +03:00
AyrisAI 01c9f5f195 feat(mobile): render exact SVG vector templates in mobile QR stand screen 2026-08-20 23:43:26 +03:00
AyrisAI f768b92873 feat(qr-stands): clean SVG template renderer with exact QR placement and no redundant overlays 2026-08-20 23:39:56 +03:00
AyrisAI eb0b5d1886 feat(qr-stands): add qr-2.svg preset from user code 2026-08-20 23:36:01 +03:00
AyrisAI 38fd0dd030 feat(qr-stands): activate user provided qr-1.svg and qr-4.svg 2026-08-20 23:34:57 +03:00
AyrisAI 18396f3b99 fix(qr-stands): restore exact user-provided qr-1.svg alongside qr-4.svg 2026-08-20 23:31:54 +03:00
AyrisAI edb7af9288 feat(qr-stands): add flat vector qr-1.svg urban preset 2026-08-20 23:30:04 +03:00
AyrisAI a0cb04b2c6 feat(qr-stands): set qr-4 as exclusive vector stand template 2026-08-20 23:25:19 +03:00
AyrisAI 4ce6505a4d feat(qr-stands): add custom-svg-3 preset with user provided SVG stand code 2026-08-20 19:03:18 +03:00
AyrisAI 8efb5a9ff6 fix: render true SVG template vector graphic as stand background 2026-08-20 18:55:21 +03:00
AyrisAI 0a2aae68db feat: add qr-2.svg template preset (Classic Bistro QR Stand 2) 2026-08-20 18:49:43 +03:00
AyrisAI 984a41d0e5 refactor: simplify QR stand presets to single urban qr-1.svg template 2026-08-20 18:44:44 +03:00
AyrisAI 04863c8a78 feat: add qr-1.svg template integration for QR stand generator 2026-08-20 18:43:15 +03:00
AyrisAI e63de8584d style(mobile): render 1:1 pixel-perfect Urban Burger tabletop plaque layout 2026-08-20 18:28:23 +03:00
AyrisAI 3a15dd15b9 feat(mobile): build native in-app QR Stand Generator with theme switcher & A5 PDF / PNG exporter 2026-08-20 18:25:20 +03:00
AyrisAI bf44bf3e9d fix(docker): resolve pnpm v10 ERR_PNPM_IGNORED_BUILDS in Dockerfile 2026-08-20 18:22:36 +03:00
AyrisAI d396cbb221 feat: implement Tabletop QR Stand Generator with high-res PNG and print-ready A5 PDF export 2026-08-20 18:16:49 +03:00
AyrisAI 54a27903c8 chore: remove confidence score step from AI menu scanner flow 2026-08-20 18:03:10 +03:00
AyrisAI 3f326fa407 feat: allow updating custom menu slug with format validation, uniqueness checking and active cache sync 2026-08-20 17:58:42 +03:00
AyrisAI e7d0bcc505 feat: implement DELETE /restaurants/:id endpoint and mobile UI danger zone for restaurant deletion 2026-08-20 17:44:55 +03:00
AyrisAI 5103322fa1 feat: dynamically fetch live Cloudflare SSL TXT verification records in GET /domains endpoint 2026-08-20 17:35:23 +03:00
AyrisAI 8adec100af feat: render CNAME and Cloudflare SSL TXT verification instructions with copy buttons in mobile app domain settings 2026-08-20 17:33:14 +03:00
AyrisAI 5cbd80326f feat: setup Supabase Storage bucket for restaurant assets and add mobile upload helper 2026-08-20 17:30:22 +03:00
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