You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TL;DR Saved searches with e-mail alerts, symmetric for both sides of the market: candidates save a job search ("remote Elixir in Köln") and get new matches by mail; recruiters save a people search ("tag:elixir ort:köln, open to offers") and get new candidates by mail.
Order: 8/9 in the Jobs & Organizations milestone. Depends on #933 (job board filters) and #928 (status visibility, for the people side). Where: new table saved_searches, save buttons on /search and /jobs, management page under /settings, a daily sweeper + Emailer mail.
Data model:
saved_searches: user_id, kind: people|jobs, query (string, 255 — the same
syntax the search/board URL uses, so saving = capturing the
current filters), notify: none|daily|weekly,
last_run_at, last_notified_at
Cap per member (config, default 10). New-results detection via high-water mark: only entities created after last_notified_at count, so a mail never repeats old results (same pattern as the DM notification high-water mark).
Want:
A saved jobs search captures the whole board filter set (the query string is the board URL: q, tag, near + radius, country, salary_min, workplace/employment type), and the sweeper's matcher runs the very same board query — radius and salary alerts behave exactly like the live board, "neue Stellen im Umkreis von 50 km um Köln ab 60.000 €" just works. A member with a stored minimum-salary expectation (Jobs 1/9: Employment-status visibility + minimum-salary expectation #928) gets a one-tap "ab meiner Gehaltsvorstellung" option when saving; it is stored as an ordinary salary filter and the figure never appears in any mail.
People search gains a status: operator/filter (status:looking, status:open) in Vutuv.Search.parse/2, honoring Jobs 1/9: Employment-status visibility + minimum-salary expectation #928's visibility: only statuses visible to signed-in members are matchable, hidden never matches. Requires login; logged-out search ignores the operator. Combined with the existing ort:/stadt: city operator and tag: this covers the recruiter's real search ("Elixir-Leute in Köln, offen für Angebote"). People matching deliberately stays city-text over member-entered addresses — no radius on people; member addresses are display data, not geocoded — and only ever matches what the searcher could see logged-in.
One quiet "Suche speichern" button on /search and on /jobs when filters are active — members who never use it see one small button, nothing else. Saving asks only for the notify cadence (none/daily/weekly); the select defaults to none (harmless default: saving a search never silently subscribes anyone to e-mail).
Management block in /settings (joins the settings hub like every area): paginated list of saved searches with query, cadence, last-result info; edit cadence, run now (jump to results), delete.
Daily sweeper (Berlin day) batches per member: one e-mail per member per day at most, listing each saved search with up to 5 new results and a link to the full list; weekly cadence collects on a fixed weekday. Built on Emailer.base_email/0 + bulk_headers/1, with a per-search one-click disable link (the unsubscribe pattern), both HTML and text bodies via the e-mail framework.
Deleting a member cascades their saved searches (extend the deletion chokepoint test).
Legal/privacy: alert mails about people contain only what the recipient could see logged-in (name, handle, headline, status pill); nothing hidden leaks by e-mail, and a member's minimum-salary expectation never rides along in an alert mail, whatever its visibility. Respect blocks: blocked members never appear in each other's alerts. SEO & GEO: none (all behind login); the job-alert mail links the public detail pages. UX: mobile-first mail layout (single column); the settings block is invisible until the first search is saved. Docs: extend docs/architecture/search.md + jobs.md; new config knobs in docs/ADMINS.md. Smoke test (browser + mail): save a jobs search with near=Köln&radius=50&salary_min=60000 plus a tag filter, publish a matching Cologne posting above the figure from a second account, run the sweeper → exactly one mail in /sent_emails listing the new posting, deep link works; publish one below the figure or outside the radius → the next sweep stays silent about it; run the sweeper again → no second mail (high-water mark); save a people search with status:looking, flip a test member's status with visibility members → next sweep mails it; set that member to hidden → they never appear; disable the search via the mail's one-click link → no further mails; German render of mail + settings checked. Out of scope: push/in-app notification channels for alerts, algorithmic recommendations ("jobs you might like"), a jobs scope chip on /search.
TL;DR Saved searches with e-mail alerts, symmetric for both sides of the market: candidates save a job search ("remote Elixir in Köln") and get new matches by mail; recruiters save a people search ("tag:elixir ort:köln, open to offers") and get new candidates by mail.
Order: 8/9 in the Jobs & Organizations milestone. Depends on #933 (job board filters) and #928 (status visibility, for the people side).
Where: new table
saved_searches, save buttons on/searchand/jobs, management page under/settings, a daily sweeper +Emailermail.Data model:
last_notified_atcount, so a mail never repeats old results (same pattern as the DM notification high-water mark).Want:
q,tag,near+radius,country,salary_min, workplace/employment type), and the sweeper's matcher runs the very same board query — radius and salary alerts behave exactly like the live board, "neue Stellen im Umkreis von 50 km um Köln ab 60.000 €" just works. A member with a stored minimum-salary expectation (Jobs 1/9: Employment-status visibility + minimum-salary expectation #928) gets a one-tap "ab meiner Gehaltsvorstellung" option when saving; it is stored as an ordinary salary filter and the figure never appears in any mail.status:operator/filter (status:looking,status:open) inVutuv.Search.parse/2, honoring Jobs 1/9: Employment-status visibility + minimum-salary expectation #928's visibility: only statuses visible to signed-in members are matchable,hiddennever matches. Requires login; logged-out search ignores the operator. Combined with the existingort:/stadt:city operator andtag:this covers the recruiter's real search ("Elixir-Leute in Köln, offen für Angebote"). People matching deliberately stays city-text over member-entered addresses — no radius on people; member addresses are display data, not geocoded — and only ever matches what the searcher could see logged-in./searchand on/jobswhen filters are active — members who never use it see one small button, nothing else. Saving asks only for the notify cadence (none/daily/weekly); the select defaults to none (harmless default: saving a search never silently subscribes anyone to e-mail)./settings(joins the settings hub like every area): paginated list of saved searches with query, cadence, last-result info; edit cadence, run now (jump to results), delete.Emailer.base_email/0+bulk_headers/1, with a per-search one-click disable link (the unsubscribe pattern), both HTML and text bodies via the e-mail framework.Legal/privacy: alert mails about people contain only what the recipient could see logged-in (name, handle, headline, status pill); nothing hidden leaks by e-mail, and a member's minimum-salary expectation never rides along in an alert mail, whatever its visibility. Respect blocks: blocked members never appear in each other's alerts.
SEO & GEO: none (all behind login); the job-alert mail links the public detail pages.
UX: mobile-first mail layout (single column); the settings block is invisible until the first search is saved.
Docs: extend
docs/architecture/search.md+jobs.md; new config knobs indocs/ADMINS.md.Smoke test (browser + mail): save a jobs search with
near=Köln&radius=50&salary_min=60000plus a tag filter, publish a matching Cologne posting above the figure from a second account, run the sweeper → exactly one mail in/sent_emailslisting the new posting, deep link works; publish one below the figure or outside the radius → the next sweep stays silent about it; run the sweeper again → no second mail (high-water mark); save a people search withstatus:looking, flip a test member's status with visibilitymembers→ next sweep mails it; set that member tohidden→ they never appear; disable the search via the mail's one-click link → no further mails; German render of mail + settings checked.Out of scope: push/in-app notification channels for alerts, algorithmic recommendations ("jobs you might like"), a jobs scope chip on
/search.