Overview
Ficha Dubai loads property data from a JSON file (property-5157395.json). The data is normalized by the normalizeProperty() function in app.js to handle different data structures consistently.
Property JSON Structure
The JSON file follows this structure:
{
"data" : {
"property" : {
"property_uuid" : "bbb8185d-2ee3-48a4-ba7f-8fecaba6e549" ,
"nid" : 49695472717 ,
"property_id" : "5157395" ,
"titulo" : "Apartamento en Venta en Las Cabañas, Bello" ,
"descripcion" : "Apartamento en venta de 79m2..." ,
"url_360" : "https://apartamento-dubai.vercel.app/?m=bE7cSwnyKad" ,
"images" : [ ... ],
"servicios" : [ ... ],
"caracteristicas_propiedad" : [ ... ],
"detalles_propiedad" : { ... }
}
},
"success" : true
}
Top-Level Fields
Main property object containing all property information
API response status indicator
Property Object Fields
Unique identifier for the property "property_uuid" : "bbb8185d-2ee3-48a4-ba7f-8fecaba6e549"
Property title/headline "titulo" : "Apartamento en Venta en Las Cabañas, Bello"
Detailed property description "descripcion" : "Apartamento en venta de 79m2, con vista exterior..."
URL for 360° virtual tour (optional) "url_360" : "https://apartamento-dubai.vercel.app/?m=bE7cSwnyKad"
Images Array
The images array contains property photos:
"images" : [
{
"url" : "venta-594a5fafcf-1.webp" ,
"order" : 1 ,
"type_img" : 1 ,
"title" : null ,
"comment" : null
},
{
"url" : "venta-cca6e41506-2.webp" ,
"order" : 2 ,
"type_img" : 1 ,
"title" : null ,
"comment" : null
}
]
Image Object Fields
Image filename or full URL. If it doesn’t start with http, it’s prefixed with images/
Display order (1-based). Images are sorted by this field
Image type identifier (1 = standard photo)
Optional image description
Services Array
The servicios array contains estimated utility costs:
"servicios" : [
{
"servicio" : "gas" ,
"estrato" : 3 ,
"valor" : 25000
},
{
"servicio" : "energia" ,
"estrato" : 3 ,
"valor" : 100000
},
{
"servicio" : "acueducto" ,
"estrato" : 3 ,
"valor" : 115000
},
{
"servicio" : "internet_tv" ,
"estrato" : 3 ,
"valor" : 125000
}
]
Service Object Fields
Service type: gas, energia, acueducto, internet_tv
Socioeconomic stratum (1-6 in Colombia)
Estimated monthly cost in local currency (COP)
Characteristics Array
The caracteristicas_propiedad array lists property features:
"caracteristicas_propiedad" : [
"Interior" ,
"Balcón" ,
"Conjunto Cerrado" ,
"Instalación de gas"
]
Each item is a simple string. Common values include: “Interior”, “Balcón”, “Conjunto Cerrado”, “Instalación de gas”, “Zona de lavandería”, “Ascensor”
Property Details Object
The detalles_propiedad object contains detailed specifications:
"detalles_propiedad" : {
"area" : 79.0 ,
"tipo_inmueble" : "Apartamento" ,
"estrato" : "3" ,
"conjunto" : "Dubai" ,
"direccion" : "CARRERA 58AA 31-166" ,
"precio_venta" : 328000000.0 ,
"precio_anterior" : null ,
"barriocomun" : "Las Cabañas" ,
"ciudad" : "Bello" ,
"num_habitaciones" : 3 ,
"num_ascensores" : 0 ,
"num_piso" : 5 ,
"baños" : 2 ,
"garajes" : 0 ,
"telefono" : "3015637932" ,
"correo" : "tati7214@gmail.com" ,
"anos_antiguedad" : 10 ,
"latitud" : 6.319948999999999 ,
"longitud" : -75.565495
}
Required Fields
Private area in square meters
Property type: “Apartamento”, “Casa”, “Local”, “Oficina”, etc.
Sale price in local currency (COP)
Optional Fields
Previous price (for showing discounts)
Socioeconomic stratum (1-6)
Latitude coordinate for map
Longitude coordinate for map
The normalizeProperty() Function
The normalizeProperty() function in app.js (lines 571-611) transforms the raw JSON into a consistent format:
const normalizeProperty = ( raw ) => {
const property = raw ?. property || raw ?. data ?. property || raw ;
const details = property ?. detalles_propiedad || {};
const images = Array . isArray ( property ?. images )
? property . images
. slice ()
. sort (( a , b ) => ( a . order || 0 ) - ( b . order || 0 ))
. map (( img ) => img . url || img )
: [];
return {
titulo: property ?. titulo ,
descripcion: property ?. descripcion ,
url_360: property ?. url_360 ,
images ,
servicios: property ?. servicios || [],
caracteristicas_propiedad: property ?. caracteristicas_propiedad || [],
tipo_inmueble: details ?. tipo_inmueble || property ?. tipo_inmueble ,
estrato: details ?. estrato || property ?. estrato ,
conjunto: details ?. conjunto || details ?. conjunto_edificio || property ?. conjunto ,
direccion: details ?. direccion || property ?. direccion ,
barrio: details ?. barriocomun || property ?. barrio ,
ciudad: details ?. ciudad || property ?. ciudad ,
departamento: details ?. departamento || property ?. departamento ,
precio: details ?. precio_venta ?? property ?. precio ,
precio_anterior: details ?. precio_anterior ?? property ?. precio_anterior ,
area_privada: details ?. area ?? property ?. area_privada ,
area_construida: details ?. area_construida ?? property ?. area_construida ,
habitaciones: details ?. num_habitaciones ?? property ?. habitaciones ,
banos: details ?. baños ?? details ?. banos ?? property ?. banos ,
parqueaderos: details ?. garajes ?? property ?. parqueaderos ,
antiguedad: details ?. anos_antiguedad ?? property ?. antiguedad ,
telefono: details ?. telefono || details ?. contacto_zona || property ?. telefono ,
correo: details ?. correo || property ?. correo ,
nombre_contacto: property ?. nombre_contacto ,
administracion: details ?. last_admin_price ?? property ?. administracion ,
latitud: details ?. latitud ?? property ?. latitud ,
longitud: details ?. longitud ?? property ?. longitud ,
estado: property ?. estado ,
};
};
What It Does
Handles Multiple Formats
Accepts data from different API response structures
Sorts Images
Automatically sorts images by the order field
Flattens Structure
Combines fields from property and detalles_propiedad into a single object
Provides Fallbacks
Uses optional chaining (?.) and nullish coalescing (??) for safe access
Normalizes Field Names
Maps inconsistent field names to a standard schema
Creating Your Own Property JSON
Minimal Example
Here’s the minimum required structure:
{
"data" : {
"property" : {
"property_uuid" : "unique-id-here" ,
"property_id" : "12345" ,
"titulo" : "Beautiful Apartment" ,
"descripcion" : "A stunning 2-bedroom apartment in the heart of the city." ,
"images" : [
{
"url" : "images/photo1.jpg" ,
"order" : 1
}
],
"detalles_propiedad" : {
"area" : 85.0 ,
"tipo_inmueble" : "Apartamento" ,
"precio_venta" : 350000000 ,
"ciudad" : "Medellín" ,
"direccion" : "Calle 10 #20-30" ,
"num_habitaciones" : 2 ,
"baños" : 2
}
}
},
"success" : true
}
Complete Example
For a fully-featured listing:
{
"data" : {
"property" : {
"property_uuid" : "abc123-def456-ghi789" ,
"property_id" : "67890" ,
"titulo" : "Luxury Penthouse with Ocean View" ,
"descripcion" : "Experience luxury living in this stunning penthouse with panoramic ocean views, modern finishes, and top-of-the-line appliances." ,
"url_360" : "https://example.com/360-tour" ,
"images" : [
{
"url" : "images/penthouse-main.jpg" ,
"order" : 1 ,
"type_img" : 1 ,
"title" : "Living Room" ,
"comment" : "Spacious living area with ocean view"
},
{
"url" : "images/penthouse-kitchen.jpg" ,
"order" : 2 ,
"type_img" : 1 ,
"title" : "Kitchen" ,
"comment" : "Modern kitchen with island"
}
],
"servicios" : [
{
"servicio" : "gas" ,
"estrato" : 6 ,
"valor" : 50000
},
{
"servicio" : "energia" ,
"estrato" : 6 ,
"valor" : 200000
}
],
"caracteristicas_propiedad" : [
"Vista al mar" ,
"Terraza" ,
"Jacuzzi" ,
"Smart Home" ,
"Gimnasio privado"
],
"detalles_propiedad" : {
"area" : 180.0 ,
"area_construida" : 200.0 ,
"tipo_inmueble" : "Apartamento" ,
"estrato" : "6" ,
"conjunto" : "Ocean View Residences" ,
"direccion" : "Avenida del Mar 500" ,
"precio_venta" : 850000000.0 ,
"precio_anterior" : 950000000.0 ,
"barriocomun" : "El Poblado" ,
"ciudad" : "Medellín" ,
"num_habitaciones" : 3 ,
"num_ascensores" : 2 ,
"num_piso" : 15 ,
"baños" : 3 ,
"garajes" : 2 ,
"telefono" : "3001234567" ,
"correo" : "contact@realestate.com" ,
"anos_antiguedad" : 2 ,
"last_admin_price" : 500000 ,
"latitud" : 6.2476 ,
"longitud" : -75.5658
}
}
},
"success" : true
}
Loading Property Data
The loadData() function in app.js (lines 665-687) loads property data:
const loadData = async () => {
// Initialize lightbox
initLightbox ();
// Check for inline data first
if ( window . PROPERTY_DATA ) {
populatePage ( window . PROPERTY_DATA );
return ;
}
// Otherwise, fetch from JSON file
try {
const response = await fetch ( "./property-5157395.json" );
if ( ! response . ok ) {
throw new Error ( `HTTP ${ response . status } ` );
}
const data = await response . json ();
populatePage ( data );
} catch ( error ) {
$ ( "#property-title" ). textContent = "No se pudo cargar el inmueble" ;
}
};
Two Loading Methods
Define property data directly in HTML: < script >
window . PROPERTY_DATA = {
data: {
property: {
// Your property data here
}
}
};
</ script >
< script src = "app.js" defer ></ script >
Load from an external JSON file (default): const response = await fetch ( "./property-5157395.json" );
const data = await response . json ();
populatePage ( data );
To use a different filename, modify the fetch URL in app.js:675.
Data Validation Tips
Always include an order field in image objects. Images without order may display in unpredictable sequence. "images" : [
{ "url" : "photo1.jpg" , "order" : 1 },
{ "url" : "photo2.jpg" , "order" : 2 }
]
Prices should be numbers, not strings. Don’t include currency symbols or thousands separators. // Correct
"precio_venta" : 328000000
// Wrong
"precio_venta" : "$328,000,000"
Latitude and longitude must be valid decimal numbers:
Latitude: -90 to 90
Longitude: -180 to 180
"latitud" : 6.319949 ,
"longitud" : -75.565495
If including a url_360, ensure it’s a valid, accessible URL. "url_360" : "https://example.com/tour"
Styling Guide Customize the visual appearance of property listings
Configuration Configure Tailwind, Analytics, and dependencies