Ecommerce Template
Next.js·React 등으로 만든 최신 전자상거래 템플릿
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Menu numérique par QR Code pour cafés et restaurants. Le client scanne un QR Code, consulte le menu, compose son panier, choisit sa table et envoie sa commande via WhatsApp. Rien d'autre dans le MVP (voir docs/VISION.md). 2. Créer le projet Supabase puis, dans le SQL Editor, exécuter dans l'ordre : • supabase/schema.sql (schéma canonique — ne pas modifier sans validation) • supabase/seed-illico-v2.sql puis update-photos.sql et update-infos.sql (Illico Presto) • supabase/seed-sanaa.sql (Sanaa Cookies & Fondant)README 전문 보기 ↗
Menu numérique par QR Code pour cafés et restaurants.
Établissements en service :
| Slug | Établissement | Mode de service | Devise |
|---|---|---|---|
illico-presto | Illico Presto Coffee (Oran) | commande à table | DZD |
sanaa-cookies | Sanaa Cookies & Fondant (Île-de-France) | retrait / livraison 92-95 | EUR |
Le client scanne un QR Code, consulte le menu, compose son panier, choisit sa table et envoie sa commande via WhatsApp. Rien d'autre dans le MVP (voir docs/VISION.md).
Next.js (App Router) · React · Tailwind CSS · Supabase (PostgreSQL)
Installer les dépendances :
npm install
Créer le projet Supabase puis, dans le SQL Editor, exécuter dans l'ordre :
supabase/schema.sql (schéma canonique — ne pas modifier sans
validation)supabase/seed-illico-v2.sql puis update-photos.sql et
update-infos.sql (Illico Presto)supabase/seed-sanaa.sql (Sanaa Cookies & Fondant)Copier .env.example en .env.local et remplir avec l'URL et la
clé « anon public » du projet Supabase (Settings → API).
Lancer :
npm run dev
Ouvrir http://localhost:3000/r/illico-presto ou http://localhost:3000/r/sanaa-cookies
.env.example → Deploy.https://<projet>.vercel.app/r/illico-presto
sur téléphone, y compris l'envoi WhatsApp.lib/services/restaurant.ts pour la carte
publique — getRestaurantBySlug ; lib/services/dashboard.ts,
lib/services/establishments.ts et
lib/services/establishment-assets.ts pour le tableau de bord
commerçant, la création d'établissement et l'identité visuelle)."use client" uniquement si
nécessaire (état du panier).node scripts/qr.mjs https://votre-domaine/r/le-slug
Produit un PNG 2000 px et un SVG vectoriel dans qr/. Toujours tester le
scan avec deux téléphones différents avant impression.
Depuis le Lot D, la création de l'établissement lui-même (identité,
compte propriétaire, catégorie initiale) passe par l'outil interne
/admin/establishments/new (voir section « Lot D » ci-dessus), pas
par un script de seed manuel. Les étapes ci-dessous restent
nécessaires pour les réglages spécifiques au mode de service que Lot D
ne couvre pas (zones livrées, produits à options) :
lib/restaurants-config.ts :
mode de service (table ou retrait/livraison), téléphone, zones
livrées, produits à options.public/banners/<slug>.jpg
(logo/cover passent désormais par Supabase Storage, voir section
« Storage » ci-dessous).L'étape 1 impose encore un déploiement pour chaque nouveau client. C'est une dette assumée : l'évolution proposée est de faire passer ces réglages en base (voir l'en-tête de
lib/restaurants-config.ts).
supabase/migration-v29-merchant-dashboard.sql in the Supabase SQL Editor.public.restaurant_users.supabase/tests/v29-isolation-tests.md./dashboard/login.The dashboard reads orders through RLS and changes status only through
public.update_order_status. Receipt printing is available on every order and
uses the per-restaurant public.receipt_settings profile (58 or 80 mm).
Outil interne réservé aux opérateurs Scanym (scanym_operators /
is_scanym_operator(), table alimentée manuellement par le CTO) :
/admin/establishments/new. Crée un établissement en statut
onboarding, avec une invitation propriétaire explicite (jamais de
compte Supabase Auth ni de mot de passe créés automatiquement — voir
supabase/migration-lotd-establishment-creation.sql). Le rattachement
réel a lieu une fois le compte du propriétaire créé manuellement par
le CTO, via link_pending_owner. Ne remplace pas l'étape 3 ci-dessus
pour les réglages spécifiques au mode de service
(lib/restaurants-config.ts), qui reste hors du périmètre de cet
outil.
Deux buckets Supabase Storage distincts, chacun avec ses propres
policies storage.objects — jamais partagées entre les deux :
| Bucket | Portée | Chemin | Policies | Migration |
|---|---|---|---|---|
product-photos | Une photo par produit du catalogue | {restaurant_id}/{product_id}/{fichier} | product_photos_select|insert|update|delete_own_restaurant — owner/manager du restaurant propriétaire du produit | supabase/migration-v67-product-photos.sql |
establishment-assets | Logo et cover de l'établissement (portée globale, pas par produit) | {restaurant_id}/{logo|cover}/{fichier} | establishment_assets_select|insert|update|delete_authorized — owner/manager du restaurant, ou tout opérateur Scanym (scanym_operators / is_scanym_operator()), pour n'importe quel établissement | supabase/migration-v68-establishment-assets.sql |
Les deux buckets sont publics en lecture (menu public consulté sans
authentification, via QR code) ; l'écriture, elle, n'est jamais
publique — réservée par policy au(x) rôle(s) ci-dessus, jamais à
anon. Le nom de fichier stocké n'est jamais dérivé de l'entrée
utilisateur (crypto.randomUUID() côté client), ce qui élimine tout
risque de traversée de chemin, de collision, et tout souci de cache
lors d'un remplacement.
restaurant_configs porte deux colonnes distinctes pour l'identité
visuelle, toutes deux nullables :
logo_url — logo/identité de l'établissement (colonne du schéma
canonique, inchangée depuis l'origine du projet) ;cover_url — photo de couverture de la carte publique (V68,
additive). NULL = aucun établissement n'est affecté ; le rendu
public replie alors sur la bannière statique /banners/<slug>.jpg
existante (components/RestaurantHeader.tsx), sans régression.Écriture exclusivement via RPC dédiées (jamais d'update direct côté
client) : set_product_photo pour les photos produit,
set_restaurant_logo / set_restaurant_cover pour l'identité
d'établissement — voir lib/services/product-photo.ts et
lib/services/establishment-assets.ts.
restaurant_configs porte aussi trois couleurs personnalisées
(primary_color/secondary_color/accent_color, format #RRGGBB
strict, V69) et un lien de localisation externe (maps_url, HTTPS
uniquement, V69/V70) — écriture via update_restaurant_colors /
update_restaurant_maps_url. maps_url est volontairement
indépendant de tout fournisseur (pas seulement Google) : absent,
aucun lien n'est fabriqué automatiquement depuis
latitude/longitude — ces coordonnées restent des données neutres,
et la carte publique n'affiche simplement pas de bouton
« Itinéraire » (voir components/RestaurantHeader.tsx et
components/RestaurantInfoBar.tsx).