Saltar al contenido
Caso · 03 / 09← Todos los trabajos

Nexora

Un CRM de marca blanca para inmobiliarias, que hoy usa Liliana Cappelli Propiedades.

Rol
Producto, arquitectura y desarrollo full-stack
Stack
Next.js 16, React 19, TypeScript, Supabase, TanStack Query, Tailwind CSS 4
Web de la inmobiliaria
Web de la inmobiliariaLas reglas de acceso viven en Postgres
(01) El problema

Una inmobiliaria trabaja con propiedades, contactos, operaciones, contratos y WhatsApp. Liliana Cappelli Propiedades, de Villa Gesell, además necesitaba una web pública con su propio nombre. Cada agente tiene que ver sólo su cartera, y el rol de dueño ve todo.

Mi rolConstruí el producto de punta a punta y lo puse en marcha para su primera inmobiliaria.
(02) ResultadosContados en el código
72rutas entre panel, web pública y vistas de impresión
62migraciones de SQL versionadas
3roles que hace cumplir la base, no la interfaz
(03) Arquitectura

Tres decisiones que lo definieron.

  1. 01

    Las reglas de acceso viven en Postgres

    Por qué. El aislamiento entre inmobiliarias y la cartera de cada agente son políticas de row-level security. El cliente nunca filtra por inmobiliaria. Un error en una pantalla no puede mostrar datos de otra.

    El costo. Las políticas cuestan más de depurar que el código de la app. Si se reasigna una operación, el agente anterior deja de recibir eventos en vivo, así que el tablero se refresca al volver a la ventana.

  2. 02

    Marca blanca por variables de entorno

    Por qué. El mismo código sirve a todas las inmobiliarias. Una variable hace que el dominio raíz sirva la web de una sola agencia y muda el panel a un subdominio app. Otra oculta el nombre NEXORA en todos lados.

    El costo. El proxy tiene que resolver choques de rutas, porque /propiedades existe en la web y en el panel. Dos hosts por agencia es más DNS para configurar.

  3. 03

    Web pública en caché por 30 días, purgada por tag

    Por qué. La web se regeneraba cada pocos minutos aunque nada cambiara, y eso consumía CPU del servidor. Ahora las páginas viven 30 días. Las acciones que cambian una propiedad o la marca llaman a revalidateTag.

    El costo. Cada camino de escritura tiene que acordarse de invalidar. Uno olvidado muestra datos viejos por semanas, y hubo que encontrar y cerrar tres huecos así.

(04) GaleríaSeguí scrolleando →
Web de la inmobiliaria
Web de la inmobiliaria · La home pública de Liliana Cappelli. Colores, secciones y datos de contacto salen de la marca configurada.
Listado de propiedades
Listado de propiedades · Se sirve desde caché y se refresca sólo cuando cambia una propiedad.
Pipeline de operaciones
Pipeline de operaciones · Arrastrar y soltar con actualización optimista. Mover una tarjeta escribe una sola fila, con orden fraccional.
Contactos
Contactos · Una tabla virtualizada con paginación por cursor, para que siga ágil con miles de filas.
(05) Qué haría después
01Correr los tests unitarios y los de roles en SQL en CI. Hoy CI sólo hace lint, typecheck y build.
02Sumar Playwright para el recorrido central: una consulta desde la web se vuelve contacto y después operación.
03Pasar de unstable_cache a "use cache" con cacheTag, así el caché y la invalidación quedan al lado del dato.
Próximo proyecto · 04 / 09
HPC →Cuatro apps web y una nativa para el Hospital Privado de Comunidad
Caso · 03 / 09

Nexora

Un CRM de marca blanca para inmobiliarias, que hoy usa Liliana Cappelli Propiedades.

Rol
Producto, arquitectura y desarrollo full-stack
Stack
Next.js 16, React 19, TypeScript, Supabase, TanStack Query, Tailwind CSS 4
Nexora
(01) El problema

Una inmobiliaria trabaja con propiedades, contactos, operaciones, contratos y WhatsApp. Liliana Cappelli Propiedades, de Villa Gesell, además necesitaba una web pública con su propio nombre. Cada agente tiene que ver sólo su cartera, y el rol de dueño ve todo.

Mi rolConstruí el producto de punta a punta y lo puse en marcha para su primera inmobiliaria.
(02) Resultados
72rutas entre panel, web pública y vistas de impresión
62migraciones de SQL versionadas
3roles que hace cumplir la base, no la interfaz
(03) Arquitectura

Tres decisiones que lo definieron.

01

Las reglas de acceso viven en Postgres

Por qué. El aislamiento entre inmobiliarias y la cartera de cada agente son políticas de row-level security. El cliente nunca filtra por inmobiliaria. Un error en una pantalla no puede mostrar datos de otra.

El costo. Las políticas cuestan más de depurar que el código de la app. Si se reasigna una operación, el agente anterior deja de recibir eventos en vivo, así que el tablero se refresca al volver a la ventana.

02

Marca blanca por variables de entorno

Por qué. El mismo código sirve a todas las inmobiliarias. Una variable hace que el dominio raíz sirva la web de una sola agencia y muda el panel a un subdominio app. Otra oculta el nombre NEXORA en todos lados.

El costo. El proxy tiene que resolver choques de rutas, porque /propiedades existe en la web y en el panel. Dos hosts por agencia es más DNS para configurar.

03

Web pública en caché por 30 días, purgada por tag

Por qué. La web se regeneraba cada pocos minutos aunque nada cambiara, y eso consumía CPU del servidor. Ahora las páginas viven 30 días. Las acciones que cambian una propiedad o la marca llaman a revalidateTag.

El costo. Cada camino de escritura tiene que acordarse de invalidar. Uno olvidado muestra datos viejos por semanas, y hubo que encontrar y cerrar tres huecos así.

(04) Galería
Web de la inmobiliaria
Web de la inmobiliaria · La home pública de Liliana Cappelli. Colores, secciones y datos de contacto salen de la marca configurada.
Listado de propiedades
Listado de propiedades · Se sirve desde caché y se refresca sólo cuando cambia una propiedad.
Pipeline de operaciones
Pipeline de operaciones · Arrastrar y soltar con actualización optimista. Mover una tarjeta escribe una sola fila, con orden fraccional.
Contactos
Contactos · Una tabla virtualizada con paginación por cursor, para que siga ágil con miles de filas.
(05) Qué haría después
01Correr los tests unitarios y los de roles en SQL en CI. Hoy CI sólo hace lint, typecheck y build.
02Sumar Playwright para el recorrido central: una consulta desde la web se vuelve contacto y después operación.
03Pasar de unstable_cache a "use cache" con cacheTag, así el caché y la invalidación quedan al lado del dato.
Próximo proyectoHPC →
Nahuel SantillánES