5. Search & discovery
Ditto Up has its own marketplace search engine. Beneath the surface it is built on three data stores — Postgres for jobs and users, Amazon Neptune (a graph database) for terms, localities and verified credentials, and Elasticsearch / Postgres full-text for free-text matching. You don't have to think about any of that to use search; this section shows you the buttons.
In this section
- 5.1 The unified search bar
- 5.2 Searching for jobs
- 5.3 Searching for candidates
- 5.4 Radius & location autocomplete
- 5.5 Browsing terms (skills, licenses, certifications, degrees)
- 5.6 Term tooltips
- 5.7 The full directories —
/all_jobsand/all_candidates- 5.8 Type-filtered results and selecting refinements
- 5.9 User search
- 5.10 Industry, organisation and title autocomplete
5.1 The unified search bar
The search bar at the top of every page (/search) is one box that searches everything — jobs, candidates, terms, businesses, posts. It is intentionally one entry point; we filter the results by type after you submit, not before.
| Query string parameter | Meaning | Example |
|---|---|---|
q |
The keyword(s). Free text. | ?q=plasma+welding |
type |
Restrict to one entity type. One of job, candidate, term, business, post. |
&type=candidate |
location |
City, state, zip or country. | &location=Austin,+TX |
radius |
Miles from the location. Supported on jobs and candidates. | &radius=25 |
work_type |
onsite / remote / hybrid. |
&work_type=remote |
salary_min, salary_max |
USD pay band. | &salary_min=80000 |
experience |
entry / mid / senior / staff / principal. |
&experience=senior |
term_type |
When type=term, filter to one of occupational_skill, license, certification, credential, education_degree, equipment, title. |
&term_type=license |
Results render in search_results.html with facet chips on the left so you can refine without retyping. The page is paginated (default 20 per page).
5.2 Searching for jobs
Three entry points all hit the same engine:
- The search bar with
?type=jobor no type filter. - The Jobs tab on the home page.
- The Browse all jobs link (
/all_jobs).
A job result card shows:
- Job title and company
- Location and work type
- Salary band (if the employer chose to show it publicly)
- The required terms as small chips
- Posted date and number of openings
- A green Apply button (login required)
Clicking the card opens /job/<job_title>/<id>. From there you can see the full description, attachments, application questions, and (if you're signed in) hit Apply to land on /job/<job_title>/<id>/apply (see 2.9 The application form).
5.2.1 Filters available for job search
| Filter | Behaviour |
|---|---|
| Location + radius | See 5.4. |
| Work type | onsite / remote / hybrid. |
| Salary | Min and/or max in USD. Job postings without published salary are hidden when you set a min. |
| Experience level | Matches the employer's setting. |
| Required term | Keep only jobs that require a specific skill/license/credential. |
| Posted within | Last 24 h / 7 days / 30 days / any. |
| Visa sponsorship | Yes / no. |
| Hiring bonus | Yes / no. |
You can stack as many of these as you like. Filters are visible in the URL so you can bookmark or share a search.
5.3 Searching for candidates
Pass ?type=candidate to the search bar (or use the Candidates tab on the home page or the Browse all candidates link at /all_candidates).
A candidate result card shows:
- Profile photo and name
- Headline
- Location
- A row of term chips (top 5)
- Intro-video play button (inline)
- Score badge of their highest-graded VBQ video, if any
- Availability and minimum-pay (if they've shown them)
Clicking the card opens /profile/<name>/<user_id>.
5.3.1 Visibility rules
You only see candidates who:
- Have visibility set to Public (or) you have a direct link to them, or you've messaged before, or you follow each other.
- Have at least one term claimed.
- Have verified their email.
Candidates whose visibility is Unlisted never appear in search; Private candidates appear only to the people they have approved.
5.3.2 Filters available for candidate search
| Filter | Behaviour |
|---|---|
| Skill / term | Required (filters down by exact term match). |
| Location + radius | Same engine as job radius search. |
| Work type preference | Onsite / remote / hybrid (matches what the candidate said in /candidate-settings). |
| Minimum-pay floor | Hide candidates whose minimum pay is above your filter ceiling. |
| Has VBQ video | Show only candidates with at least one published VBQ. |
| Score band | Expert / Advanced / Proficient / Developing / Emerging — matches the highest-band VBQ for the term in question. |
| Willing to relocate | Yes / no. |
| Posted within | Last 24 h / 7 days / 30 days. |
5.3.3 Saving a candidate search
If you're an employer, click Save this search on the results page. The search is stored and you'll get email alerts whenever a new candidate matches. Manage saved searches at /recruiter/subscribe-search/ (and unsubscribe at /recruiter/unsubscribe-search/<id>/). See 3.8 Recruiter subscriptions and saved searches.
5.4 Radius & location autocomplete
Radius search ("within X miles of Y") is one of the platform's core features. It uses Ditto Up's own locality database before falling back to Google Maps.
5.4.1 The autocomplete
Anywhere you see a location field — registration, profile, job posting, search filter — it calls /place-auto-complete as you type. The endpoint runs a 3-tier dispatch:
- Address tier — if your input looks like a US street address (digits + text), the system queries our internal OpenAddresses dataset (currently ~37,000+ vertices for City of Mountain View, with the rest of the top-10 metros rolling out). Source label
local_address. - Locality tier — if it doesn't look like an address, it queries our internal GeoNames locality database (~41,500 US localities). Returns city / state / zip with coordinates. Source label
local. - Google fallback — if neither tier matches, it forwards to Google Maps Places API. The result is cached to Neptune as
source='google_cached'so the next person who types the same query gets it served from us, not Google.
You don't pick the tier — it happens transparently. The result you click sets latitude/longitude on the form so radius search works consistently across the site.
5.4.2 Place details
After you click a suggestion, the form calls /place-details to get the structured pieces (street_number, street_name, unit, city, state, zip, country, lat, lng) for storage.
5.4.3 Radius search
To find every locality within N miles of a zip / city, the platform exposes:
GET /localities-within-miles?zip_code=94103&miles=5
This returns a list of zips sorted by Haversine distance. Job and candidate search use it under the hood when you set a radius parameter.
For employers thinking about ad spend or commute analysis, this endpoint is a fast, free way to query the database directly.
5.5 Browsing terms (skills, licenses, certifications, degrees)
Every term in the marketplace has a public detail page at:
/<term_type>/<term_name>/<term_ctid>/
Where:
<term_type>isoccupational-skills/license/certification/credentials/education-degree/equipment/title.<term_name>is the URL-slugged name (for exampleplasma-arc-welding).<term_ctid>is the Credential Transparency Identifier (or our internal UUID if the term doesn't have a CTID yet).
The detail page (term_details.html) includes:
- The term's definition (auto-generated by LLM and verified, if not curated).
- The hierarchy chain (parent term → grandparent term → top-level type).
- Marketplace insights — number of jobs that require it, number of candidates who claim it, average pay band, geographic concentration.
- Candidates with published VBQ videos for this term, sorted by score band.
- Open jobs that require it.
- Sibling and related terms.
The hierarchy chain is not computed live (that was a known memory leak — see project memory). Hierarchies are pre-built and cached.
5.5.1 Verifiable credentials on the term page
Terms that come from the Credential Engine (CE) registry have an issuer field linking to the issuing organisation. Some terms are issued as W3C Verifiable Credentials — see Section 8 — Credentials & wallet.
5.6 Term tooltips
Anywhere a term appears as a chip — on a profile, in a job listing, in a search result — hovering it triggers a small tooltip served by /tooltip. The tooltip shows:
- The term type and name.
- Definition (truncated to ~200 chars, click to expand).
- Marketplace stats (X jobs, Y candidates).
- Direct link to the term detail page.
The tooltip is loaded lazily via AJAX so it doesn't slow down list rendering.
5.7 The full directories — /all_jobs and /all_candidates
If you want to browse rather than search:
| Page | URL | Default sort |
|---|---|---|
| All jobs | /all_jobs |
Newest first. |
| All candidates | /all_candidates |
Newest profile first; pinned candidates float to the top. |
Both pages have the same filter bar as their search counterparts and both are fully paginated. Both honour visibility rules — only public candidates appear in /all_candidates.
5.8 Type-filtered results and selecting refinements
Two extra endpoints help you stay on a single results page while changing the type filter:
| URL | Purpose |
|---|---|
/type-results |
Same as /search but locked to a specific entity type. Used by the type tabs ("Jobs / Candidates / Terms") on the search results page. |
/select-results |
POST handler that records facet selections and re-renders without losing the current keyword / location. |
You normally won't hit these directly — they're called by the on-page facet UI.
5.9 User search
To find a specific user (by name or email) — for example to start a new conversation:
/search-users/?q=<name+or+email>
This is a thin endpoint that returns a JSON list (or HTML row list) of users matching the query. It is used by the New conversation modal in the inbox (/messages/compose/) and by the @mention autocomplete in posts and messages.
It respects visibility rules — Private users do not show up unless you already share a conversation or follow each other.
5.10 Industry, organisation and title autocomplete
Three small autocomplete endpoints power form fields across the site:
| Endpoint | Used in | Returns |
|---|---|---|
/sugg |
Job-title and headline fields | Top 10 occupation titles starting with the typed prefix, drawn from the term graph. |
/org-sugg |
Business-name and "previous employer" fields | Top 10 organisation names from our directory + LinkedIn dictionary. |
/industry-location-sugg |
Job posting industry / location combo | Suggests industries and matching locations together so a "Healthcare in Boston" query autocompletes both halves. |
These are used silently by the form code; you'll just see autocomplete dropdowns appear as you type.
Next: 6. Messaging — the platform's biggest single subsystem.