Skip to content
Alvaro Sarria
Menú
← Todo el trabajo

HomeBrew Apartments

Buscador sin servidor de 100 alquileres de corta estancia en Madrid, Berlín y París, con búsqueda debounced, lista de guardados y publicación.

Problema

Los portales de alquiler suelen estar saturados de anuncios y tener una búsqueda lenta. Quería una experiencia de exploración rápida y centrada para una única fuente de anuncios.

Enfoque

Una aplicación de página única en React sin servidor, sin base de datos y sin API: el catálogo de 100 anuncios viaja con la app como un archivo JSON, y todo lo que guardas o publicas se almacena en el localStorage del navegador. Esa restricción da forma a casi todo el diseño. Buscas por ciudad o país, abres un anuncio para ver sus fotos, datos, desglose de precio y anfitrión, guardas los que te gustan y puedes publicar un anuncio propio en la misma cuadrícula.

Arquitectura

  • Estado: App.jsx es la única fuente de verdad. No hay contexto ni store — el estado baja por props, de forma deliberada, para una app de este tamaño
  • El catálogo se carga mediante un hook useCatalogue que importa dinámicamente el JSON de anuncios, manteniéndolo fuera del chunk inicial
  • Los resultados de búsqueda se derivan, nunca se almacenan: se recalculan a partir del conjunto completo de anuncios más una consulta debounced en cada render
  • Persistencia: los anuncios guardados son ids en localStorage, y los objetos se resuelven contra el catálogo completo; los anuncios creados por el usuario se anteponen a él
  • Estilos: CSS Modules por componente sobre un sistema de diseño en tokens.css — ningún valor hexadecimal ni número mágico de píxeles fuera de ahí

Decisiones clave

  • Derivar los resultados en lugar de almacenarlos corrigió un fallo real: una versión anterior los guardaba en su propio estado y se desincronizaban del campo de búsqueda. Por lo mismo, las búsquedas de un anuncio van contra el catálogo completo y nunca contra la vista filtrada, que devuelve undefined para todo lo que la búsqueda actual excluye
  • ApartmentCard está memoizado y recibe un booleano plano en vez de un predicado isFavorite, cuya identidad cambia en cada alternancia y volvería a renderizar las 100 tarjetas
  • El catálogo se genera en tiempo de compilación a partir del volcado de datos original, descartando en torno al 60% de campos que nada renderiza — el archivo generado se versiona para que un clon nuevo funcione al instante
  • La serif de display lleva el logotipo y todos los números — precios, valoraciones, recuentos por ciudad — mientras que el texto de interfaz usa la pila de fuentes del sistema

Resultados

Un buscador responsivo sobre 100 anuncios con búsqueda por ciudad y país insensible a mayúsculas y con debounce, un contador por ciudad en vivo sobre la cuadrícula que hace además de chips de filtro y de control de reinicio, una lista de guardados y anuncios publicados que sobreviven a una recarga, y temas claro y oscuro que siguen la preferencia del sistema hasta que eliges uno. Una suite en Vitest cubre los fallos que ocurrieron de verdad, y el linter corre sin tolerar ni un aviso.

Qué haría diferente

Paginaría o virtualizaría la cuadrícula — el filtrado en el cliente lo necesitaría con un conjunto de datos mucho mayor que este. La limitación más importante es localStorage: los anuncios guardados y publicados nunca salen del navegador donde se crearon, así que un backend real es el siguiente paso, no una optimización.