Svelte Commerce
A standalone open-source storefront built with SvelteKit, headless across 26 commerce backends. MIT licensed.
Mermelada de mora hecha en Usme. Mira el proceso completo y verifica tu lote.
Translation pending
CommerceJavaScript · CSSGitHub @ronalc90OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Sitio web, trazabilidad de lotes y generador de etiquetas para imprimir de SaborPuro, la mermelada de mora elaborada por Mujeres Usmeñas en Usme, Bogotá D.C.
Sirve a dos públicos: a quien compra el frasco, que puede ver cómo se hizo, entender qué dice cada campo de la etiqueta y verificar su lote; y a quien produce, que planea cada tanda e imprime etiquetas que cumplen el rotulado colombiano sin hacer cuentas a mano.
Demo en vivo: https://saborpuro.lat (también en https://saborpuro.vercel.app)
Sitio público (/)
L261018-01) consulta en la API
qué día se produjo la tanda, con qué proporciones y hasta cuándo rinde.prefers-reduced-motion.Generador de etiquetas (/etiquetas)
API de trazabilidad (apps/api)
POST /api/lotes) y devuelve el lote, su etiqueta y su
código de barras en SVG.X-Clave.| La etiqueta, campo por campo | Planeador de tandas |
|---|---|
| Generador de etiquetas | En el celular |
|---|---|
Capturas tomadas del sitio en vivo con Playwright (1280 × 800 y 390 × 844).
| Parte | Tecnología |
|---|---|
Web (apps/web) | Next.js 15 (App Router), React 19, JavaScript y CSS propio, sin framework de estilos. Fuentes Fraunces, Karla y JetBrains Mono. |
API (apps/api) | Fastify 5, @fastify/cors y PostgreSQL con pg. Las tablas (lotes, pedidos, etiquetas) se crean solas al arrancar. |
Lógica compartida (packages/brand) | JavaScript ESM sin dependencias. Next lo transpila con transpilePackages. |
| Pruebas | node:test, el corredor nativo de Node. |
| Infraestructura | Vercel (web) y Railway con Nixpacks (API y Postgres). Monorepo con npm workspaces, Node 22. |
apps/web Next.js 15 — sitio público y generador → Vercel
apps/api Fastify + PostgreSQL — trazabilidad → Railway
packages/brand Lógica compartida y tokens de marca
packages/brand es el corazón del proyecto:
| Módulo | Qué hace |
|---|---|
tokens.js | Identidad de marca y datos legales. Archivo único de configuración. |
barcode.js | EAN-13: generación, validación, dígito verificador y render SVG. |
lote.js | Códigos de lote, fechas de producción y vencimiento. |
nutricional.js | Perfil nutricional desde la receta y evaluación de sellos frontales. |
etiqueta.js | Arma la etiqueta completa y valida campos obligatorios. |
plantilla.js | Plantilla editable del generador: tamaños, hojas, capacidad por hoja y validación. |
Para cambiar el nombre, los colores, el NIT o el registro sanitario, se
toca solo packages/brand/src/tokens.js: todo lo demás se actualiza
con él.
Datos de ejemplo.
tokens.jstrae a propósito datos de relleno («Fabricante de ejemplo», «Calle Falsa 123», teléfono300 000 0000, NIT y registro con ceros): ningún dato personal real vive en el repositorio. Los de verdad se escriben en el generador y se guardan con cada etiqueta en el servidor.
Requisitos: Node 22 (está en .nvmrc; el mínimo es 20) y npm. PostgreSQL solo
hace falta para la verificación de lotes y el catálogo de productos.
git clone https://github.com/ronalc90/chela
cd chela
npm ci
npm run dev:web # http://localhost:3000
Con eso funcionan el sitio público, el planeador y el generador (el borrador queda en el navegador). Sin API, la verificación de lotes avisa que el servicio no está conectado.
Para tener también la API:
# Postgres local (por ejemplo, con Docker)
docker run -d --name chela-pg -e POSTGRES_PASSWORD=chela -p 5432:5432 postgres:16
# API en http://localhost:8080; crea las tablas al arrancar
DATABASE_URL="postgres://postgres:chela@localhost:5432/postgres?sslmode=disable" \
ETIQUETAS_CLAVE="clave-local" \
npm run dev:api
# Web apuntando a esa API
printf 'NEXT_PUBLIC_API_URL=http://localhost:8080\nETIQUETAS_CLAVE=clave-local\n' > apps/web/.env.local
npm run dev:web
sslmode=disable apaga TLS para la base local. Sin CORS_ORIGINS, la API
acepta cualquier origen.
Desde la raíz del repositorio:
| Script | Qué hace |
|---|---|
npm run dev:web | Servidor de desarrollo de Next.js en el puerto 3000. |
npm run dev:api | API con node --watch en el puerto 8080 (o PORT). |
npm run build:web | Compilación de producción de la web (next build). |
npm run build:api | La API no tiene paso de compilación (Node ejecuta src/ directo) y no define build, así que este script falla. |
npm test | Las 20 pruebas de packages/brand. |
npm run start --workspace=@chela/api | Arranca la API en modo producción; es lo que ejecuta Railway. |
npm run start --workspace=@chela/web | Sirve la web ya compilada (next start). |
npm test
Son 20 pruebas con node:test sobre la lógica compartida; no necesitan
instalar dependencias ni base de datos.
packages/brand/test/core.test.mjs (13): dígito verificador y estructura del
EAN-13, render SVG, lote de ida y vuelta, vencimiento a fin de mes, perfil
nutricional, sello de azúcares y armado y validación de la etiqueta.packages/brand/test/plantilla.test.mjs (7): plantilla por defecto,
normalización y límites, tamaños predefinidos, lote y vencimiento manuales,
sellos y EAN propio, campos obligatorios y capacidad por hoja (A4, Carta y
horizontal).La web y la API no tienen pruebas automáticas.
En GitHub Actions (.github/workflows/ci.yml), cada PR y cada push a main
corren con Node 22 npm ci, npm test, npm run build:web y una
comprobación de sintaxis de apps/api.
Web → Vercel. Proyecto saborpuro (framework Next.js, Node 22), con los
dominios saborpuro.lat, www.saborpuro.lat y saborpuro.vercel.app. Cada
cambio en main se publica en producción y cada PR tiene su vista previa.
Variables: NEXT_PUBLIC_API_URL y, opcional, ETIQUETAS_CLAVE.
API → Railway. railway.json y nixpacks.toml definen el despliegue: Node
22 con Nixpacks, instalación de los workspaces, arranque con
npm run start --workspace=@chela/api, chequeo de salud en /health y
reinicio automático si falla. Railway enlaza Postgres e inyecta
DATABASE_URL.
apps/web
| Variable | Para qué |
|---|---|
NEXT_PUBLIC_API_URL | URL pública de la API en Railway. Sin ella, la verificación de lote avisa que el servicio no está conectado. |
ETIQUETAS_CLAVE | Secreto de servidor, sin prefijo NEXT_PUBLIC_. Si está, el puente /api/etiquetas pone la clave por su cuenta y la biblioteca abre sin pedir nada; entonces cualquiera que abra el sitio puede ver, editar y borrar las etiquetas. Si no está, la biblioteca pide la clave y la guarda en ese navegador. |
apps/api
| Variable | Para qué |
|---|---|
DATABASE_URL | Postgres. Railway la inyecta al enlazar el servicio. Sin ella la API arranca, pero los endpoints de datos fallan. |
CORS_ORIGINS | Orígenes permitidos, separados por coma. Los *.vercel.app se permiten siempre. |
ETIQUETAS_CLAVE | Clave de /api/etiquetas, comparada contra la cabecera X-Clave. Sin ella esas rutas responden 503 en vez de quedar abiertas. |
PORT | Lo asigna Railway. En local, 8080 por defecto. |
LOG_LEVEL | Nivel de los logs de Fastify (info por defecto). |
Cada producto guardado es su rótulo completo (ver @chela/brand/plantilla) más
una foto opcional. La foto no se imprime: sirve para reconocerlo en el
catálogo de /etiquetas. Se redimensiona y se recomprime a JPEG en el
navegador antes de subirla (máximo 900 KB), y se guarda además una miniatura
(máximo 80 KB) que es la única que viaja en el listado.
En /etiquetas, tras configurar la tanda, usa el botón de imprimir y en
el diálogo del navegador desactiva «ajustar a la página» y deja la
escala en 100 %. Las etiquetas están medidas en milímetros, así que
cualquier reescalado las saca de tamaño.
La hoja imprime solo las etiquetas: el panel, el menú y los fondos se ocultan automáticamente.
La etiqueta sigue:
La mermelada lleva sello «EXCESO EN AZÚCARES». El umbral es 10 % o más de la energía total proveniente de azúcares libres, y una mermelada tradicional lo supera con holgura. Llevar un sello prohíbe toda declaración de propiedad nutricional o de salud en la etiqueta.
El código de barras actual no sirve para retail. Usa prefijo interno
200, válido para control propio. Un GTIN comercial lo asigna GS1
Colombia (LOGYCA); el prefijo de país es 770.
Los valores reales de teléfono, NIT y registro no se escriben en el repositorio: van en el generador. El generador marca en pantalla los campos que siguen pendientes.
Los valores nutricionales del sitio son estimaciones calculadas desde la receta. No sustituyen un análisis de laboratorio.