Ecommerce Template
Next.js·React 등으로 만든 최신 전자상거래 템플릿
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
PWA offline-first para comerciantes de mercados de abastos. Inventario inteligente, ventas con ticket (imprimir / WhatsApp), semáforo de frescura y registro de mermas a un tap — pensada para manos ocupadas, luz solar directa y conexión inestable. Stack: Next.js 16 (App Router, TypeScript) · Tailwind CSS · shadcn/ui · Lucide · Supabase (Postgres + Auth + RLS) · Dexie/IndexedDB · React Query · Zustand · Web Speech API.README 전문 보기 ↗
PWA offline-first para comerciantes de mercados de abastos. Inventario inteligente, ventas con ticket (imprimir / WhatsApp), semáforo de frescura y registro de mermas a un tap — pensada para manos ocupadas, luz solar directa y conexión inestable.
Stack: Next.js 16 (App Router, TypeScript) · Tailwind CSS · shadcn/ui · Lucide · Supabase (Postgres + Auth + RLS) · Dexie/IndexedDB · React Query · Zustand · Web Speech API.
npm install
cp .env.example .env.local # opcional: rellena tus claves de Supabase
npm run dev # http://localhost:3000
Sin backend también funciona. Si no configuras Supabase, la app corre en modo local: la primera vez crea un acceso protegido con clave en el dispositivo y guarda todo en IndexedDB (puedes cargar productos de ejemplo desde el inventario vacío). Con Supabase configurado, el login es con correo y contraseña y los datos se respaldan en la nube.
| Modo | Cuándo | Cómo ingresa |
|---|---|---|
| Supabase | .env.local con URL y anon key | Correo + contraseña (registro incluido). La sesión persiste y funciona sin internet. |
| Local | Sin .env.local | Una cuenta por dispositivo con clave (PBKDF2, con bloqueo tras 5 intentos). Protege el acceso a la app; los datos de IndexedDB no están cifrados. |
En Supabase, si activas Confirm email, el usuario debe confirmar su correo antes de ingresar.
Cada venta (rápida o desde Ventas → Nueva venta) genera un ticket numerado con detalle, descuento, método de pago (efectivo/Yape/Plin/tarjeta) y vuelto. Desde el ticket puedes imprimir (58 mm u 80 mm, o "Guardar como PDF"), enviar por WhatsApp (al celular del cliente si lo registraste), copiar o compartir. Ajusta papel, dirección, RUC/DNI y mensaje en Ajustes; ahí mismo hay un ticket de prueba. El ticket es de control interno, no reemplaza una boleta o factura electrónica SUNAT.
Formas de imprimir
| Opción | Cuándo usarla |
|---|---|
| Bluetooth directo (ESC/POS) | Impresora térmica BLE con Chrome/Edge (Android o PC, HTTPS o localhost). Empareja una vez en Ajustes → Impresora; después imprime con un toque. No funciona en iPhone/iPad. |
| RawBT (solo Android) | Impresoras Bluetooth clásicas (SPP), que Web Bluetooth no ve. Instala la app RawBT y usa el botón del ticket. |
| Diálogo del sistema / PDF | Cualquier impresora instalada en el dispositivo (USB, Wi‑Fi, servicio de impresión de Android) o «Guardar como PDF». |
El ticket ESC/POS usa la página de códigos PC858 (acentos, ñ, ¿, ¡). Activa Cortar el papel solo si tu impresora tiene cortador.
Con Supabase, el dueño agrega cajeros por correo en Ajustes → Equipo (la persona debe haberse registrado antes). El cajero puede vender, ver el inventario y cobrar fiados; no puede anular ventas, ver reportes, editar/reabastecer productos, registrar mermas, cerrar caja ni cambiar el negocio. Se aplica en la interfaz, en los repositorios y en la base de datos (RLS).
/recuperar) y cambio desde Ajustes → Seguridad.npm run build
npm run start
supabase/migrations/0001_init.sql — 6 tablas, enums, índices, RLS
(aislamiento total por comerciante) y triggers de stock, PPC, merma y timestamps.supabase/migrations/0002_sales.sql — tablas sales y sale_items (tickets).
Sin este script las ventas no se sincronizan.supabase/migrations/0003_team_credit_reports.sql — stock mínimo, costo por
línea de venta, anulaciones, fiado (clientes y abonos), equipo con roles y las
políticas RLS actualizadas. Ejecútalo antes de usar la app con Supabase: el
cliente ya envía estos campos y, sin el script, la sincronización se detiene.http://localhost:3000) a Redirect URLs.anon key (Project Settings → API) a .env.local.El semáforo de frescura se recalcula tanto en el cliente (offline) como en el
servidor vía la función fn_recalc_freshness(owner).
mercadocontrol/
├─ supabase/migrations/0001_init.sql # Esquema + RLS + triggers
├─ public/
│ ├─ manifest.json # PWA
│ └─ sw.js # Service Worker (offline + background sync)
├─ src/
│ ├─ app/ # Rutas (App Router)
│ │ ├─ layout.tsx providers.tsx # Raíz: fuente, React Query, AuthProvider
│ │ ├─ (auth)/login/ # Pantalla pública de acceso
│ │ └─ (app)/ # Pantallas privadas (protegidas por SessionGate)
│ │ ├─ page.tsx # Dashboard
│ │ └─ inventario/ ventas/ mermas/ cierre/ remates/ ajustes/
│ ├─ components/
│ │ ├─ ui/ # Primitivas (button, card, sheet, stepper, feedback…)
│ │ ├─ layout/ # AppShell, Sidebar, TopBar, BottomNav, FAB
│ │ ├─ auth/ ticket/ sales/ settings/
│ │ ├─ dashboard/ inventory/ mermas/ cierre/
│ ├─ lib/
│ │ ├─ auth/ # Contrato AuthService + Supabase / Local
│ │ ├─ supabase/client.ts # Cliente Supabase
│ │ ├─ db/ # Dexie, repositorios (productos, ventas, ajustes), sync, sesión
│ │ ├─ print/ # Impresión por iframe aislado
│ │ └─ logic/ # Lógica PURA y testeable: frescura, PPC, ticket, carrito,
│ │ # reportes, WhatsApp, parser de voz
│ ├─ hooks/ # React Query + Web Speech API
│ ├─ stores/ # Zustand (estado de UI)
│ └─ types/ # Tipos de dominio
syncQueue como mutación pendiente.lib/db/sync.ts) vacía la cola hacia Supabase con
upsert idempotente cuando hay conexión, disparado por el evento online o
por Background Sync del Service Worker.Hecho para el mercado. 🇵🇪