Monorepo con tres workspaces: backend (Express + TypeScript), frontend (React + Vite) y un paquete compartido de acceso a datos (SQLite por defecto con soporte para drivers modulares).
apps/backend: API REST que acorta URLs, genera QR y redirige (GET /:code).apps/frontend: SPA que consume la API y muestra el QR generado.packages/database: utilidades compartidas para conectarse a SQLite y mantener el esquema.
- Node.js >= 18
- npm >= 9
npm install- Backend:
cp apps/backend/.env.example apps/backend/.envy ajustaPORT,BASE_URL,FRONTEND_URLyDATABASE_URLsi apuntas a otra ruta de base de datos. La raiz del backend (GET /) redirige aFRONTEND_URL. - Frontend:
cp apps/frontend/.env.example apps/frontend/.envy defineVITE_API_BASE_URL. - Base de datos:
cp packages/database/.env.example packages/database/.env. Puedes definirDATABASE_DRIVER(por defectosqlite) yDATABASE_URLen funcion del driver elegido.
npm run build # compila database, backend y frontendLa primera vez que inicies el backend con SQLite local, ensureDatabase() creara el archivo y la tabla necesarios. Para apuntar a otra ruta (por ejemplo una carpeta compartida o :memory:) cambia DATABASE_URL.
npm run dev: ejecuta backend (tsx watch) y frontend (vite) en paralelo.npm run dev:backend/npm run dev:frontend: servicios individuales.npm run build: compila los tres workspaces.npm run lint: ESLint sobre el monorepo.npm run test: tests del backend (Vitest + Supertest).
El repositorio incluye una configuracion de monorepo en vercel.json que construye el frontend con @vercel/static-build y expone el backend Express como funcion serverless (apps/backend/vercel.ts). Las rutas se resuelven asi:
/api/*y/healthvan directo al backend.- Cualquier segmento sin
.(https://dominio/abc123) se redirige al backend para resolver short codes. - Rutas restantes sirven los artefactos del frontend (SPA con fallback a
index.html).
Pasos sugeridos:
- Conecta el repositorio en Vercel y selecciona la raiz (
url-shortener-qr/). - Define variables de entorno:
- Backend:
BASE_URLyFRONTEND_URLapuntando a tu dominio publico (ej.https://tu-app.vercel.app). AjustaDATABASE_URLpara usar una base remota, ya que las funciones serverless no persisten en disco. - Frontend:
VITE_API_BASE_URLcon la misma URL publica del backend.
- Backend:
- Ejecuta
vercel --prod(o usa el dashboard) para desplegar.
Si prefieres dominios separados (ej. app. para el frontend y la raiz para los codigos), configura los dominios personalizados en Vercel y actualiza BASE_URL, FRONTEND_URL y VITE_API_BASE_URL en consecuencia.
El paquete @url-shortener/database expone:
- Registro de drivers modulares mediante
registerDatabaseDriver(name, factory)y seleccion dinamica conDATABASE_DRIVERosetDatabaseDriver(). - Inicializacion automatica del esquema con
ensureDatabase()(el driversqlitecrea tabla e indices si no existen). - Helpers listos para usar:
insertUrl,findUrlByCode,incrementUrlHits,removeAllUrlsygetDatabase()(devuelve la conexion nativa del driver activo). - Configuracion mediante
DATABASE_URL(acepta rutas absolutas o relativas, el prefijofile:o:memory:para entornos efimeros) u opciones propias del driver que registres.
Si necesitas ampliar el modelo (por ejemplo agregar expiracion o propietario), edita los helpers en packages/database/src/index.ts y aplica los cambios correspondientes en el backend.
url-shortener-qr/
|- apps/
| |- backend/
| | |- src/
| | |- tests/
| | `- package.json
| `- frontend/
| |- src/
| |- public/
| `- package.json
|- packages/
| `- database/
| |- src/
| `- package.json
|- docs/
| `- architecture.md
|- package.json
|- .eslintrc.cjs
|- .eslintignore
`- .gitignore
- Agregar nuevos campos al modelo (expiracion, etiquetas, propietario) y actualizar las consultas en
packages/database. - Registrar un driver adicional (p. ej. Postgres) que implemente las mismas operaciones para entornos escalados.
- Exponer estadisticas (ej.
hits) en endpoints y reflejar las metricas en el frontend. - Configurar pipelines de despliegue (backend en Railway/Fly.io, frontend en Vercel) compartiendo la misma base o replicando SQLite.
- Integrar autenticacion y un panel administrativo para gestionar URLs.