Saltar al contenido
Boilerplate de e-commerce open source

Clona el repo. Lanza una tienda.

Una tienda, un panel de administración y pago con Stripe listos para producción en un repo. Cambia el backend, conserva la app.

0variables de entorno para arrancar
El catálogo de demostración sirve la tienda hasta que conectes una.
4backends, una interfaz
Demo, Firebase, Supabase, Postgres. Adaptadores, no forks.
18productos de demostración
Filtros, búsqueda, variantes y stock, ya poblados.
2idiomas, 4 monedas
Resueltos en el servidor, así el primer render ya es correcto.
Lo que viene incluido

Una tienda entera, no una landing con carrito.

Cada pantalla de abajo es este repositorio, sobre una base de datos poblada y sin ninguna credencial configurada — la misma compilación que CI produce en cada push.

La portada de la tienda: titular a gran escala junto a una fotografía de producto
Un hero editorial sobre fotografía real, y luego el catálogo. El color de marca, el idioma y la moneda cambian en caliente.
Backends

Una interfaz de comercio. Cambia el backend.

Cada llamada de la tienda y del panel pasa por un módulo de comercio tipado. Cambia el adaptador y conserva la app.

.env.local

NEXT_PUBLIC_COMMERCE_BACKEND=firebase
Implemented in
src/lib/commerce/firebase.ts
Credentials
NEXT_PUBLIC_FIREBASE_*

Predeterminado sin configuración. Las reglas de Firestore vienen en el repo.

Cumple esto y la app funcionasrc/lib/commerce/types.ts

Siete servicios, un objeto. Todas las llamadas de la tienda y de la administración pasan por él; por eso un adaptador es un archivo nuevo y no un fork.

export interface CommerceServices {
  products:   ProductService;
  carts:      CartService;
  quotes:     QuoteService;
  orders:     OrderService;
  discounts:  DiscountService;
  customers:  CustomerService;
  admin:      AdminService;
}

// one of the seven, in full:
interface ProductService {
  list(pageSize?: number, cursor?: PageCursor | null): Promise<ProductPage>;
  getById(id: string): Promise<Product | null>;
  search(term: string, maxResults?: number): Promise<Product[]>;
  create(product: Product): Promise<void>;
  update(id: string, data: Partial<Product>): Promise<void>;
  delete(id: string): Promise<void>;
  listFeatured(): Promise<Product[]>;
  feature(product: Product): Promise<void>;
  unfeature(featuredId: string): Promise<void>;
}
A dónde va una llamada

Una línea de código. Cuatro destinos posibles.

La misma línea de la tienda llega a un catálogo incluido, a Firestore o a una base SQL. Lo que cambia es qué adaptador responde, y si la respuesta viene del navegador o del servidor.

Cualquier llamada de tienda o administración

await commerce.products.list()

Una interfaz tipada — CommerceServices

En el navegador

  • Demounset

    src/lib/commerce/demo

    Catálogo incluido. Sin red ni credenciales.

  • Firebasefirebase

    src/lib/commerce/firebase.ts

    Lecturas directas desde el navegador; las reglas mandan.

En el servidor

POST /api/commerce/[service]/[method]
Verifica el token, comprueba el rol y registra la auditoría

  • Supabase / Prismasupabase · postgres

    src/lib/commerce/server/*.ts

    Las credenciales privilegiadas nunca salen del servidor.

  • Admin writesany backend

    src/lib/commerce/server/firebase-admin.ts

    Escrituras de administración, viva donde viva el dato.

Funciones

Todo lo que necesita una tienda real, ya conectado.

Studio Headphones X1

Northsound

Studio Headphones X1

AUD-001

$129.99

Audio

Panel de administración

CRUD de productos, medios, pedidos y flujo de cotizaciones.

Cotizaciones y pago con Stripe

Como invitado o con sesión, con webhooks verificados por firma.

Multi-idioma y multi-moneda

Enrutamiento por idioma y cambio de moneda en vivo, incluidos.

Inventario y roles

Conteo de stock, estados sin stock y acceso de administrador por rol.

Lo que lo sostiene

Las partes fáciles de equivocar, ya resueltas.

Un starter solo merece un fork si sus cimientos aguantan el contacto con producción. Estos son los que normalmente no lo hacen.

  • El checkout no puede vender de más

    api/webhooks/stripe/route.ts

    El webhook de Stripe escribe el pedido y cada descuento de stock en una sola transacción, con la clave de la sesión. Un reenvío toca el mismo documento; dos simultáneos no pueden gastar la última unidad.

  • Las escrituras de administración quedan auditadas

    lib/commerce/server/audit.ts

    Las mutaciones privilegiadas pasan por el servidor, que vuelve a comprobar el rol y registra quién cambió qué con su propio reloj. Un administrador no puede omitir ni retrasar la entrada.

  • Los precios salen del catálogo

    api/checkout/route.ts

    La ruta de checkout vuelve a leer cada producto y variante en el servidor. Nada de lo que envía el navegador mueve un importe.

  • Cada push pasa por el control

    .github/workflows/ci.yml

    Lint, tipos, la suite de pruebas y una compilación de producción sin ninguna credencial. El backend de demostración es lo que hace posible esto último.

Del clon a la tienda

Tres comandos. Sin cuenta, sin base de datos, sin claves.

Node 20.9 y una terminal es toda la lista de requisitos. No hay imagen de Docker que descargar ni nada que aprovisionar antes de que la tienda arranque.

  1. Clona e instala

    $ git clone github.com/nebulanollie/ecommerce-boilerplate$ npm install

    Un solo árbol de dependencias y ningún compilador nativo que satisfacer. El paso de postinstall solo construye el índice de la documentación.

  2. Arráncala

    $ npm run dev

    El catálogo de demostración responde a cada lectura: 18 productos, filtros por categoría, búsqueda, variantes, un carrito y un pago que se confirma en local.

  3. Decide dónde vive el dato

    $ echo "NEXT_PUBLIC_COMMERCE_BACKEND=sqlite" >> .env.local

    Una variable de entorno. SQLite te da escrituras reales contra un archivo sin instalar nada; Postgres, Supabase y Firebase piden una cadena de conexión o un proyecto.

Esta misma compilación corre en CI sin ninguna credencial, que es lo que impide que este camino se pudra.

Leer el inicio rápido
Antes de clonarlo

Las preguntas que conviene hacerse primero.

Incluidas las respuestas que no favorecen.

¿Esto está listo para producción o es una demo?

Las partes listadas en Garantías están hechas para producción y cubiertas por pruebas: los caminos del dinero, la matriz de control de acceso, la traza de auditoría y el adaptador SQL contra una base real. Lo que no es, es un producto alojado — tuyo son el despliegue, la cuenta de pagos, los textos legales y la decisión sobre lo que tu tienda necesita y aquí no está.

¿Tengo que usar Firebase?

No. El dato vive donde apunte COMMERCE_BACKEND, y la identidad es un interruptor aparte: AUTH_PROVIDER=authjs ejecuta Auth.js con las sesiones en tu propia base SQL, así que un despliegue con Postgres o SQLite no necesita ningún proyecto de Firebase. El único emparejamiento fijo es Firestore como almacén, porque las firestore.rules incluidas dependen de request.auth.

¿Y si mi backend no es ninguno de los cuatro?

Escribe un archivo que cumpla CommerceServices y selecciónalo con una variable de entorno. Nada en la tienda ni en la administración importa un SDK de proveedor — esa es la regla que existe para imponer toda esta capa, y TypeScript rompe la compilación en cuanto a un adaptador le falta un método.

¿Qué falta a propósito?

Tarifas de envío, cálculo de impuestos, suscripciones y marketplaces multivendedor. Cada uno es una decisión de producto sin un valor por defecto neutral, y una suposición equivocada incrustada en un starter cuesta más quitarla que ponerla. Las listas de precios por moneda y el renderizado estático del cambio de moneda siguen abiertos, y están en ROADMAP.md.

¿Cómo recibo actualizaciones después de cambiar cosas?

Igual que con cualquier starter: mantén este repositorio como un segundo remoto y fusiona lo que quieras. No hay canal de actualizaciones ni framework que actualizar — el código es tuyo desde que lo clonas, que es el trato que hace un boilerplate.

¿Cuál es la licencia?

MIT. El uso comercial, los forks cerrados y el cambio de marca están permitidos, sin exigir atribución en tu producto. La atribución se agradece, no se exige.

Código abierto. Auto-alojable. Tuyo para clonar.

git clone github.com/nebulanollie/ecommerce-boilerplate

Funciona sin configuración. Conecta un backend cuando quieras datos reales.