Product · how-to
Property Listings
Upload photos, set price and status, open houses, agents, and CSV import — on the agent’s own site from the owner desk. Not Shop. Not a live MLS feed.
Who this is for.
Owners (e.g. Leonardo Armas) use Part A.
Studio / The 100 Club use Part B to enable the module, seed brands, and support clients.
Part A — Owner: upload & manage listings
A1. Open Listings
- Sign in to the owner desk for your brand.
- Left menu → Listings.
- Ensure the checkbox Listings module on is checked (or request it from Home if you cannot toggle).
A2. Create one listing
- New listing.
- Fill Title (required), subtitle, status, type, price or price label, address, beds/baths/sqft/year.
- Write description + highlights (one per line).
- Photos — multi-select JPG/PNG/WebP, max ~8 MB each. First image = cover.
- Optional: open house times/notes, agent roster pick, MLS #, external URL, Featured.
- Save listing.
A3. Status meanings
| Status | Public effect |
|---|---|
| Active | Available on the market |
| Pending | Under contract badge |
| Sold | Sold badge (often muted card) |
| Coming soon | Pre-list tease |
| Archived | Hidden from public (desk still has record) |
A4. Photos best practices
- Lead with a strong exterior or hero living space.
- Prefer landscape images for the cover card (4:3-ish).
- Remove a photo with × then save again.
- Image URLs can also be set via CSV
image_url/imagecolumn (public URL).
A5. Open house & agent
- Open house start/end show on the public detail page with optional notes.
- Build a team under Agents / team, then select on each listing (fills name/email/phone if empty).
- You can still type agent fields manually per listing.
A6. CSV bulk import
- Sample CSV → download headers + examples.
- Edit in Excel / Google Sheets → save as CSV.
- Import CSV → paste or upload → Run import.
- Same
mls_id= update existing; new mls_id = create.
Aliases accepted: title/name, price/list_price, address/street, beds/bedrooms, baths/bathrooms, sqft/square_feet, mls_id/mls_number, agent_name, open_house_start, featured, image_url, …
A7. Public pages
- Index: brand
/listingsorlistings.html?site={slug} - Detail:
listing.html?site={slug}&slug={listing-slug} - API (for custom themes):
GET /portal/api/public/listings?site={slug}
A8. Leonardo Armas specifically
- Brand slug:
leonardo-armas - Luxury site: local preview
http://127.0.0.1:8088/ - Full brand guide: 15 · Leonardo Armas owner
Part B — Studio: enable, support, ops
B1. Enable Listings on a brand
- Studio → brand → Modules → turn
listingson, or - Owner desk with IT mode: feature toggle, or
- API / script: set
features_json.listings = trueonportal_sites. - Confirm public API:
GET /api/public/listings?site={slug}returnsenabled: true.
Portal reload. After shipping listings code, Reload Portal in Server Control so routes are live. Owners will 404 until then.
B2. New real-estate client checklist
- Create portal site (slug, name, accent, public URL).
- Enable
listings(and portal/website as needed). - Deploy public pages: at minimum template
listings.html+listing.html, or custom luxury theme (see Leonardo). - Nginx:
/portal/proxy to :8091 so public pages hit the API same-origin. - Seed sample listings if desired:
node scripts/seed-listings-demo.jsor brand-specific seed. - Give owner login + this manual (Help tab auto-shows Listings guide when module is on).
B3. Data & files
- DB tables:
listings,listing_agents(migrate inlib/listings.js). - Photos:
portal-app/data/listings-media/{siteId}/served as/portal/listings-media/…. - Phase 3 fields: open house, agent snapshot, mls_id / mls_source / external_url.
B4. Business API (authenticated desk)
| Method | Path | Use |
|---|---|---|
| GET | /api/business/listings?site= | List + agents + enabled |
| POST | /api/business/listings | Create |
| POST | /api/business/listings/:id | Update / archive |
| POST | /api/business/listings/upload | Photo data URL |
| POST | /api/business/listings/import | CSV text |
| GET | /api/business/listings/csv-sample | Sample CSV |
| GET/POST/DELETE | /api/business/listings/agents | Roster |
| POST | /api/business/listings/feature | Toggle module |
B5. Custom site (Leonardo pattern)
- Folder:
nginx…/html/clients/leonardo-armas/ - JS loads
/portal/api/public/listings?site=leonardo-armas; falls back to demo if API offline. - Owner desk:
/portal/business.html?site=leonardo-armas - Nginx conf:
conf/sites/leonardo-armas.conf(port 8088) — Reload Nginx as admin. - Seed:
node scripts/seed-leonardo-armas.js
B6. Support tips
- “Listings missing” → module off, portal not reloaded, or wrong
site=slug. - “Photo failed” → size/type; check disk on listings-media path.
- “CSV duplicate homes” → they forgot matching
mls_id. - Do not put houses in Shop products.
B7. Manuals for the client
- Universal desk: 10-owner-desk-universal
- Leonardo brand: 15-owner-leonardo-armas
- This product page: Help tile when
listingsis on - Studio catalog: studio/11-listings (ops summary)