Aplicación web para registrar, seguir y reseñar libros, inspirada en Letterboxd pero orientada a lecturas. Proyecto personal de portfolio, enfocado en una arquitectura clara, UX cuidada y un stack sencillo y mantenible.
| Dark (Mocha) | Light (Latte) |
|---|---|
![]() |
![]() |
| Búsqueda | Detalle de libro |
|---|---|
![]() |
![]() |
| Mis lecturas | Perfil |
|---|---|
![]() |
![]() |
| Capa | Tecnología |
|---|---|
| Backend | Laravel 11 + Blade |
| Base de datos | PostgreSQL |
| Frontend | SCSS + Vite (BEM, sin Tailwind) |
| Temas | Catppuccin Mocha / Latte |
| Entorno | DDEV · Docker · PHP 8.2 · nginx-fpm |
| Tests | PHPUnit · SQLite in-memory |
Requisitos: DDEV
git clone git@github.com:CristianSG2/ReadOn.git
cd ReadOn
ddev start
ddev composer install
ddev npm install
ddev artisan key:generateAñadir en .env:
GOOGLE_BOOKS_API_KEY=tu_api_key
ddev artisan migrate
ddev npm run build
ddev launchddev artisan db:seedCrea un usuario demo con libros de ejemplo. Requiere GOOGLE_BOOKS_API_KEY configurada en .env.
- Email:
demo@readon.app - Contraseña:
password
Autenticación manual (sin Breeze):
- Login, registro y logout propios
- Middleware auth en rutas protegidas
- CSRF, regeneración de sesión y throttle de login
- Redirección post-login a
/me
- Búsqueda vía Google Books API con resultados filtrados por idioma (español primero, inglés después) y sin portada
- Guardado de libros en lista personal sin recarga de página
- Estados: Wishlist, Leyendo, Leído, Abandonado
- Rating de 0.5 a 5 estrellas (escala en medias estrellas) y reseñas
- Edición y borrado de registros propios sin recarga de página
Todas las acciones sobre un registro se realizan sin recarga de página:
- Rating y estado: se guardan automáticamente via fetch PATCH al interactuar
- Reseña: guardado y eliminación via fetch, con actualización del DOM en tiempo real
- Guardar libro: desde el detalle, via fetch sin redirección
- Eliminar registro: con confirmación nativa y fade-out de la card en el DOM
El feedback de cada acción se muestra mediante toast notifications (esquina inferior derecha), consistentes en toda la app y adaptadas al tema activo.
Sistema de fallback en tres niveles:
- Thumbnail de Google Books (forzado a HTTPS para evitar mixed-content)
- Open Library por ISBN (
/b/isbn/{ISBN}-L.jpg) si Google Books no devuelve portada - Placeholder SVG local (
/images/no-cover.svg) si ninguna fuente tiene imagen
Mientras cargan las portadas se muestra un skeleton loader con animación shimmer que respeta el tema activo (Mocha/Latte). El ISBN se extrae de industryIdentifiers en la respuesta de Google Books y se persiste en reading_logs.
Vista /me con:
- Estadísticas de lectura (total, wishlist, leyendo, leído, abandonado)
- Media de ratings
- Últimos 5 registros, clicables — enlazan al detalle del libro
- Acceso al listado completo
Paleta Catppuccin con roles de color diferenciados:
| Token | Mocha (dark) | Latte (light) | Rol |
|---|---|---|---|
--accent |
Lavender #b4befe |
Rosewater #dc8a78 |
Links, nav activo |
--primary |
Mauve #cba6f7 |
Rosewater #dc8a78 |
Botones CTA |
--accent-2 |
Mauve #cba6f7 |
Flamingo #dd7878 |
Hover, estados secundarios |
El switch dark/light persiste entre sesiones vía localStorage. El tema se aplica antes del primer render (script inline en <head>) para evitar flash. Ningún color está hardcodeado fuera del bloque de tokens.
- Transiciones de página: fade-out al salir, fade-in al entrar
- Cards: animación
fadeInUpescalonada al cargar la página - Skeleton loader: shimmer animado en portadas mientras cargan, respetando el tema
- Toast notifications: sistema unificado de feedback para todas las acciones
Componente Blade reutilizable (<x-logo size="sm|md|lg" />): icono SVG bookmark + wordmark "ReadOn" en tres tamaños, todo via tokens CSS.
Página standalone con:
- Topbar con logo, toggle dark/light y CTA de acceso
- Hero a dos columnas: tagline + CTAs / estantería SVG decorativa con colores de la paleta activa
- Estado autenticado: muestra el nombre del usuario y enlaza a
/books
Login y registro con el mismo layout de dos columnas que la homepage: formulario a la izquierda y estantería SVG decorativa a la derecha. Los botones comparten los mismos tokens de color que el resto de la app.
v1.1.1 — desplegado en producción: 🌐 readon.cristiansg.dev
- Flujo de lectura operativo de extremo a extremo
- Inline saves: todas las acciones sin recarga de página
- Toast notifications unificadas en toda la app
- Skeleton loader en búsqueda y Mis lecturas
- Animaciones de entrada y transiciones de página
- Sistema de portadas con fallback multinivel
- Homepage rediseñada con visual SVG adaptativo
- Tokens Catppuccin con roles diferenciados por función
- Logo como componente reutilizable
- SCSS limpio: sin duplicados, sin código muerto, sin utilidades inline
- 16 Feature tests (auth, reading logs, perfil) — SQLite en memoria
- Búsqueda filtrada por idioma (ES primero, EN después) y sin resultados sin portada
ddev php artisan testConfigurados con SQLite en memoria (phpunit.xml). Cubren auth, logs de lectura y perfil — 16 tests, 42 assertions.
ddev npm run dev
ddev npm run build
ddev artisan optimize:clearLicencia MIT





