WallpaperMachine
The wallpapers you love. A new home on your Mac.
Describe the home you want in your own words. HomeScout AI finds it across Egypt.
LifestyleGitHub @AmrabrazekOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗An experiment in where an LLM belongs in search. Homes in Egypt are the test case.
Type "family of 4 near AUC, max 12M" or "3 owad fel tagamo3 ta7t 15 mil" and HomeScout turns it into real filters, shows what it understood, and searches by meaning for the rest.
flowchart LR
Q["family of 4 near AUC, max 12M"] --> R["Regex parser<br/>free · instant · tested"]
R -->|"max 12M"| F["Hard filters"]
R -->|"leftover words only"| L["LLM (Haiku)<br/>validated · cached · capped"]
L -->|"2+ beds · New Cairo"| F
L -.->|"timeout or bad output"| R
F --> S["Hybrid search<br/>keyword + vectors"]
The rule: code does what code can do, and the LLM only gets the words code couldn't parse. Every claim below is measured.
| Check | Result |
|---|---|
| Query parsing, regex only | 21/35 queries fully right |
| Query parsing, regex + LLM on the leftovers | 34/35 fully right · p50 2.0 s, p95 4.1 s (only when regex leaves words) |
| Semantic ranking, local e5 embeddings | 69% relevant in top 10 vs 37% for random order |
Full report, including where embeddings lost: docs/evals/search.md (npm run eval).
How the search works, with live examples: interactive write-up (source: docs/search/index.html).
| Feature | How it works |
|---|---|
| Free-text search | A regex parser turns "3 bedrooms in New Cairo under 12M" into hard filters, and the UI shows what it understood. An LLM handles only the words regex missed (Arabic, "family of 5", landmarks). That path is behind a flag, validated against the schema, cached and capped, and falls back to regex. |
| Hybrid search | Typo-tolerant keyword search plus vector search in Typesense. The listing, the concierge and the feed all share one filter builder. |
| Similar units | Filter by type, region and price band, then cosine top 30 from pgvector, then a weighted rerank on price, size, bedrooms and location, with at most 2 per project. Every result carries its reasons. |
| Buyer profile | An anonymous cookie, stated preferences, and views, saves and skips. A time-decayed taste vector is built from the embeddings of units the buyer engaged with. |
| Concierge agent | Vercel AI SDK with tools that call typed NestJS endpoints (search_units, compare_units, find_similar, update_preferences…). Tool results render as UI cards, and the model writes only the "why it fits". Traced in Langfuse. |
| "Why it fits you" | Deterministic checks of each unit against the buyer's stated preferences. It shows misses too, so nothing shown to the buyer is guessed. |
| "For you" feed | Ranks units that meet the buyer's preferences by their taste vector, with a penalty for units like ones they skipped. |
| Evals | npm run eval scores parsing, ranking, the feed and similar units against fixed fixtures; agent evals are in progress. |
flowchart LR
subgraph web["Next.js 13"]
P["Pages"]
C["/api/chat<br/>AI SDK agent"]
E["/api/events<br/>view · save · skip"]
end
API["NestJS API"]
PG[("Postgres 16 + pgvector<br/>source of truth")]
W["pg-boss worker<br/>embed (e5 / OpenAI)"]
TS[("Typesense<br/>search projection")]
P -->|GraphQL| API
C -->|"tools: REST /internal/*"| API
E --> API
C -.->|traces| LF["Langfuse"]
API --> PG
PG -->|"job in the same transaction"| W
W --> PG
W --> TS
API --> TS
API --> M[("MinIO<br/>images")]
npm run reindex), so the search index can never become the only copy of anything.EMBEDDING_MODEL switches between a free local model (e5-small, runs in Node)
and OpenAI. Vectors are stored per model, so models can be compared side by side.LLM_PROVIDER / LLM_MODEL pick the model. Tools are plain REST endpoints with
their own tests.The full roadmap and decision log live in issue #12.
Requirements: Docker with Docker Compose.
git clone https://github.com/Amrabrazek/homescout-ai.git homescout-ai
cd homescout-ai
docker compose up --build
On first start the backend applies database migrations, seeds sample data, and indexes it into Typesense. Then open:
homescout, password homescout-secret)Every setting has a working local default. To override one, copy .env.example to .env and edit it.
Reset everything (database, search index, images):
docker compose down -v
Run the infrastructure in Docker and the apps on your machine:
docker compose up postgres typesense minio minio-init
# backend
cd backend
cp .env.example .env
npm install
npm run db:seed # apply migrations + seed if empty
npm run start:dev # API + sync worker; embeds and indexes new units
npm run reindex # (new terminal, first run) enqueue every unit for embedding + indexing
# frontend (new terminal)
cd frontend
cp .env.example .env # set ANTHROPIC_API_KEY to use the concierge chat
npm install
npm run dev
| Where | Command | What it does |
|---|---|---|
| backend | npm run db:migrate | Apply pending migrations |
| backend | npm run db:migrate:revert | Revert the last migration |
| backend | npm run db:seed | Migrate, then seed sample data if DB is empty |
| backend | npm run db:seed -- --reset | Replace all data with fresh sample data |
| backend | npm run reindex | Enqueue every unit: re-embed if changed, rebuild the Typesense index |
| backend | npm run lint / typecheck | Static checks |
| backend | npm test / test:e2e | Unit tests / API tests |
| frontend | npm run lint / typecheck | Static checks |
CI runs lint, typecheck, tests and a production build on every pull request.
backend/
src/
config/ database config shared by the app and migration CLI
migrations/ versioned schema migrations (TypeORM)
common/ entities, Typesense client
modules/ developer, project, unit, amenity, image, upload,
embedding (providers), sync (pg-boss worker), search (hybrid search + filters)
scripts/ seed generator (scripts/seed/) + reindex
frontend/
src/app/ App Router pages (listing, unit detail, dashboard)
src/components/ UI components
src/lib/ Apollo client, GraphQL operations, storage helper
docker-compose.yml the full local stack
API references: backend/API_DOCUMENTATION.md, backend/API_QUICK_REFERENCE.md,
backend/GRAPHQL_PLAYGROUND_EXAMPLES.md.
Next.js 13 · NestJS · TypeORM · GraphQL · Postgres 16 + pgvector · Typesense · pg-boss · MinIO · Vercel AI SDK ·
Langfuse · Docker Compose · GitHub Actions. Built with Claude Code; see
CLAUDE.md for the agent's project guide.