Inspiration
We've all felt it: sitting in a lecture hall, a cafe, or on a train, surrounded by people, yet completely disconnected. The person next to you might love the same obscure band, the same niche game, the same show you can't stop thinking about. But you'll never know, because there's no way to find out.
Wavelength started with a simple question: what if you could see your people, right now, right here?
What it does
Wavelength is a real-time proximity matching app that finds culturally compatible people around you, anonymously. You build a taste profile (music, shows, games, interests), and we show you who nearby shares your wavelength. You only appear to each other when the feeling is mutual.
The map shows nearby users as hearts. The darker the heart, the stronger the compatibility. Red strings connect you to each match. Click a heart to see your compatibility score and shared interests. Start a conversation if you want.
No names. No photos. Just vibes.
How we built it
The matching engine: Elasticsearch at the core
We don't use Elasticsearch as a database. We use it as a matchmaker.
Every user is stored as a dense_vector in an Elasticsearch index, a 20-dimensional cultural taste profile. When a user's GPS updates, we fire a hybrid kNN + geo query:
POST users/_search
{
"knn": {
"field": "vector",
"query_vector": [...],
"k": 10,
"num_candidates": 50,
"filter": {
"geo_distance": {
"distance": "2km",
"location": { "lat": -33.87, "lon": 151.20 }
}
}
}
}
One query. Finds your 10 most culturally compatible people. Filters by 2km radius. Returns cosine similarity scores. All inside Elasticsearch, no separate vector database needed.
Interest vectorisation: Groq LLaMA 3.3 70B
When you save your profile, we send your interests to Groq's LLaMA 3.3 70B model and ask it to generate a 20-dimensional cultural taste vector across dimensions like:
- mainstream vs indie
- emotional vs intellectual
- dark vs lighthearted
- casual vs hardcore gaming
- fast-paced vs contemplative
This turns "Radiohead, Elden Ring, Succession" into a point in 20D cultural space. Two people who've never heard the same song can still be a 90% match because they occupy the same cultural space.
Real-time delivery: Socket.io
Every time a user's GPS updates, a new kNN + geo query fires against Elasticsearch via Socket.io WebSockets. Matches are delivered to the map in real time. No refresh needed.
Privacy by design
- Anonymous identity: you are never revealed unless it is mutual
- No exact coordinates are ever exposed
- Auto-deletion: users are removed from Elasticsearch on signout or browser close
- Supabase handles auth and permanent profile storage separately from the ephemeral presence layer in ES
Tech stack
- Frontend: Next.js, TypeScript, Tailwind CSS, Framer Motion, Leaflet.js
- Backend: Node.js, Express, Socket.io
- ML/AI: Groq LLaMA 3.3 70B
- Search/Matching: Elasticsearch (Elastic Cloud)
- Auth/DB: Supabase
Challenges we faced
The dense_vector ghost problem
Elasticsearch stores dense_vector fields outside of _source for performance reasons. This means a normal get or index call returns the document without the vector, it is completely invisible. We spent hours thinking vectors were not saving, trying different upsert approaches and refresh timings, before discovering we needed docvalue_fields to retrieve them. The vector was there the whole time.
Race conditions on location updates
Location events fire rapidly and simultaneously. Two updates for the same user would trigger version_conflict_engine_exception in ES as they tried to update the same document concurrently. Fixed with retry_on_conflict: 3 on all update operations.
LLM non-determinism
Using an LLM as an embedding model means the same interests can produce slightly different vectors on each run. We mitigated this with temperature: 0 and alphabetically sorting tags before vectorisation, but it is an inherent limitation of the approach.
What we learned
- Elasticsearch is far more powerful than most people use it for.
dense_vector+ kNN + geo in a single query is genuinely impressive - Real-time systems require careful thought about race conditions and eventual consistency
- The hardest bugs are the ones where everything looks broken but is actually working fine (the vector was always there!)
- Building something emotionally resonant is just as important as building something technically impressive
What's next
- Real embeddings (nomic/OpenAI) for deterministic, higher-dimensional matching
- Spotify and Letterboxd integration to pull taste data automatically
- Mutual reveal mechanic with cryptographic verification
- Group wavelengths: find your people at events and concerts
- Recommender system: "because you like Radiohead, you might vibe with people who like Portishead"
- Invisibility mode: browse nearby matches without appearing on anyone else's map
- Privacy controls: choose who can see you (everyone / matches only / nobody)
- Filters: age range, gender, looking for (friends / dating / networking)
- Block and report system
- Location expiry: automatically disappear from the map after a set time even without signing out
Built With
- api
- elasticsearch
- knn
- leaflet.js
- next.js
- node.js
- supabase
- websockets
Log in or sign up for Devpost to join the conversation.