Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Ozcaar/real-estate-template/llms.txt
Use this file to discover all available pages before exploring further.
propertiesService is the single point of entry for all property data in the template. Every page and component that needs property records must go through this service — reading from sampleProperties directly is explicitly prohibited. This design means the backing data source can be swapped from the static MVP array to an API call (e.g. $fetch('/api/properties')) without touching a single component: only the service implementation changes.
All methods are synchronous over the static MVP data, which keeps SSR rendering deterministic. When a future async data source is introduced, the method signatures will gain a
Promise wrapper but the filter/sort semantics documented here will remain identical.Supporting Types
PropertyFilters
The typed filter shape accepted by filter(). All fields are optional — an undefined value means “no constraint on this field”, so callers can pass a raw useRoute().query object without sanitizing it first.
PropertySort
Allow-listed sort orders for the listing page. Additional values can be added here in the future without touching the data model.
| Value | Behavior |
|---|---|
'featured' | Featured properties first, then by id ascending (default) |
'price-asc' | Cheapest first, id ascending as tiebreaker |
'price-desc' | Most expensive first, id ascending as tiebreaker |
isPropertySort
PropertySort allow-list. Use this before passing a query param to filter().
The value to test. Typically a raw
useRoute().query field.true when value is one of 'featured', 'price-asc', or 'price-desc'.Methods
getAll()
status: 'hidden' are excluded. This is the base visibility gate that all other methods build on — when you need the full catalog without additional filters, use getAll() rather than accessing sampleProperties directly.
All non-hidden properties. May be an empty array if the catalog contains only hidden records.
getBySlug()
undefined when the slug is not found or when the matching property has status: 'hidden'. Route pages should map an undefined result to a 404 error.
The URL-safe slug string from
Property.slug. Typically sourced from route.params.slug.The matching property, or
undefined when the slug does not exist or the property is hidden.filter()
undefined filter values are treated as “no constraint” so passing an unsanitized route.query object is safe.
A
PropertyFilters object with optional operation, type, and location fields. Any field that is undefined or an empty string is ignored.Sort order for the result set. Defaults to
'featured' when omitted. Must be one of the PropertySort values; use isPropertySort() to validate raw URL params before passing them here.The filtered and sorted list of visible properties. An empty array when no properties match the criteria.
| Field | Match strategy |
|---|---|
operation | Exact match against Property.operationType (sale / rent), case-insensitive via toLowerCase() |
type | Exact match against Property.propertyType (house, apartment, land, commercial, office), case-insensitive |
location | Accent-insensitive substring match across Property.location + city + state + country (see note below) |
/properties listing page reads these four query params:
| Param | Maps to | Notes |
|---|---|---|
operation | filters.operation | sale or rent |
type | filters.type | house, apartment, land, commercial, office |
location | filters.location | Free text; accent-insensitive |
sort | sort argument | Validated via isPropertySort(); falls back to 'featured' |
getFeatured()
featured flag is true. Accepts an optional limit for showcase widgets that display only a fixed number of cards (e.g. the homepage hero section renders three featured properties).
Maximum number of properties to return. When omitted, all featured properties are returned.
Visible, featured properties — sliced to
limit when provided.getRelated()
current using a weighted scoring model over the visible catalog. The result is used by the related-properties section on the property detail page. Only available and reserved properties are eligible candidates — sold, rented, and hidden properties are never surfaced. The current property itself is always excluded from results.
The reference property. Its
propertyType, operationType, city, country, developmentId, agentId, and price fields drive the scoring weights.Maximum number of related properties to return. Defaults to
3.Up to
limit related properties ordered by score descending, then by featured descending, then by id ascending for determinism.| Criterion | Points |
|---|---|
Same propertyType | +3 |
Same operationType | +2 |
Same city | +2 |
Same country (only when city did not match) | +1 |
Same developmentId (sibling units in a project) | +2 |
Same agentId | +1 |
Price within 30% of current.price | +1 |
status === 'available' or status === 'reserved' are eligible as related candidates. Sold, rented, and hidden properties are never surfaced.
Graceful fallback: When no candidates score above zero — for example in a near-empty catalog — the method falls back to getFeatured(limit), applying the same eligibility filter so the current property and non-available records are still excluded.
Example
Architecture Notes
Components must never importsampleProperties directly. All reads go through propertiesService so the data source can be replaced (e.g. swapped to $fetch('/api/properties')) without touching the component tree.
Property type and all its supporting union types (PropertyOperationType, PropertyType, PropertyStatus, PropertyCoordinates) live in ~/features/properties/types/property.types.ts. A matching Zod runtime schema is available at ~/features/properties/schemas/property.schema.ts for validating external data at the boundary before it enters the service layer.