<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Job discovery on Raven</title><link>https://raven.nopejs.me/docs/job-discovery/</link><description>Recent content in Job discovery on Raven</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://raven.nopejs.me/docs/job-discovery/index.xml" rel="self" type="application/rss+xml"/><item><title>How discovery works</title><link>https://raven.nopejs.me/docs/job-discovery/how-it-works/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://raven.nopejs.me/docs/job-discovery/how-it-works/</guid><description>&lt;h1 id="how-job-discovery-works">
 How job discovery works
 &lt;a class="anchor" href="#how-job-discovery-works">#&lt;/a>
&lt;/h1>
&lt;p>Deep dive: architecture, data flow, and what Raven does &lt;strong>not&lt;/strong> do.&lt;/p>
&lt;p>&lt;strong>Module:&lt;/strong> &lt;code>jobs/discover.mjs&lt;/code> · &lt;strong>CLI:&lt;/strong> &lt;code>raven discover&lt;/code>&lt;/p>
&lt;hr>
&lt;h2 id="tldr">
 TL;DR
 &lt;a class="anchor" href="#tldr">#&lt;/a>
&lt;/h2>
&lt;p>&lt;code>raven discover&lt;/code> does &lt;strong>not&lt;/strong> search Google or scrape arbitrary websites. It runs up to four &lt;strong>parallel tiers&lt;/strong> that pull structured job data from public APIs and feeds, filters client-side, deduplicates by canonical apply URL, and saves to &lt;code>data/jobs.json&lt;/code>.&lt;/p>
&lt;pre tabindex="0">&lt;code class="language-mermaid" data-lang="mermaid">flowchart LR
 A[raven discover] --&amp;gt; B[ATS APIs]
 A --&amp;gt; C[Board feeds]
 A --&amp;gt; D[Local SQLite]
 A --&amp;gt; E[hiring.cafe optional]
 B --&amp;gt; F[merge + dedup]
 C --&amp;gt; F
 D --&amp;gt; F
 E --&amp;gt; F
 F --&amp;gt; G[data/jobs.json]
&lt;/code>&lt;/pre>&lt;hr>
&lt;h2 id="what-search-means">
 What &amp;ldquo;search&amp;rdquo; means
 &lt;a class="anchor" href="#what-search-means">#&lt;/a>
&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Mechanism&lt;/th>
 &lt;th>How listings are found&lt;/th>
 &lt;th>Default discover?&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>ATS reverse scan&lt;/td>
 &lt;td>Public JSON API per company board&lt;/td>
 &lt;td>Yes&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Board feeds&lt;/td>
 &lt;td>Aggregator APIs (RemoteOK, Remotive, …)&lt;/td>
 &lt;td>Yes&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>openjobdata index&lt;/td>
 &lt;td>SQL on &lt;code>data/jobs.db&lt;/code>&lt;/td>
 &lt;td>Yes (needs sync)&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>hiring.cafe&lt;/td>
 &lt;td>POST search API&lt;/td>
 &lt;td>Opt-in&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>WebSearch / &lt;code>search_queries&lt;/code>&lt;/td>
 &lt;td>Google-style &lt;code>site:&lt;/code> queries&lt;/td>
 &lt;td>&lt;strong>Not implemented&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>scan_method: websearch&lt;/code>&lt;/td>
 &lt;td>Per-company handoff&lt;/td>
 &lt;td>&lt;strong>Log only&lt;/strong>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Zero LLM, zero browser by default.&lt;/p></description></item><item><title>Sources &amp; tiers</title><link>https://raven.nopejs.me/docs/job-discovery/sources/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://raven.nopejs.me/docs/job-discovery/sources/</guid><description>&lt;h1 id="job-sources">
 Job sources
 &lt;a class="anchor" href="#job-sources">#&lt;/a>
&lt;/h1>
&lt;p>Raven orchestrates discovery tiers in parallel via &lt;code>jobs/discover.mjs&lt;/code>. Each tier uses &lt;strong>public APIs or feeds&lt;/strong> — not web search engines.&lt;/p>
&lt;blockquote>
&lt;p>Full architecture: &lt;a href="how-it-works/">How discovery works&lt;/a> · WebSearch status: &lt;a href="scan-strategies/">Scan strategies&lt;/a>&lt;/p>&lt;/blockquote>
&lt;h2 id="tier-1--live-ats-apis---sources-ats">
 Tier 1 — Live ATS APIs (&lt;code>--sources ats&lt;/code>)
 &lt;a class="anchor" href="#tier-1--live-ats-apis---sources-ats">#&lt;/a>
&lt;/h2>
&lt;p>Reverse-scans public company directories and hits each platform&amp;rsquo;s zero-auth JSON API.&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Platform&lt;/th>
 &lt;th>Careers URL pattern&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Greenhouse&lt;/td>
 &lt;td>&lt;code>job-boards.greenhouse.io/{slug}&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Lever&lt;/td>
 &lt;td>&lt;code>jobs.lever.co/{slug}&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Ashby&lt;/td>
 &lt;td>&lt;code>jobs.ashbyhq.com/{slug}&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Workday&lt;/td>
 &lt;td>&lt;code>{tenant}.wd{N}.myworkdayjobs.com/{site}&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Rippling&lt;/td>
 &lt;td>&lt;code>ats.rippling.com/{slug}/jobs&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Workable&lt;/td>
 &lt;td>&lt;code>apply.workable.com/{slug}&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>BambooHR&lt;/td>
 &lt;td>&lt;code>{tenant}.bamboohr.com/careers&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>SmartRecruiters&lt;/td>
 &lt;td>&lt;code>careers.smartrecruiters.com/{slug}&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Recruitee&lt;/td>
 &lt;td>&lt;code>{slug}.recruitee.com&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Pinpoint&lt;/td>
 &lt;td>&lt;code>{slug}.pinpointhq.com&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Teamtailor&lt;/td>
 &lt;td>&lt;code>{slug}.teamtailor.com&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Personio&lt;/td>
 &lt;td>&lt;code>{slug}.jobs.personio.de&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Company slug lists come from openjobdata (after &lt;code>raven sync-jobs&lt;/code>) or bundled caches in &lt;code>data/cache/ats-companies/&lt;/code>.&lt;/p></description></item><item><title>Scan strategies</title><link>https://raven.nopejs.me/docs/job-discovery/scan-strategies/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://raven.nopejs.me/docs/job-discovery/scan-strategies/</guid><description>&lt;h1 id="scan-strategies">
 Scan strategies
 &lt;a class="anchor" href="#scan-strategies">#&lt;/a>
&lt;/h1>
&lt;p>&lt;code>portals.example.yml&lt;/code> documents a &lt;strong>4-level strategy&lt;/strong> for job discovery beyond default tiers. This page maps each level to what Raven runs automatically today.&lt;/p>
&lt;hr>
&lt;h2 id="four-levels-from-portalsexampleyml">
 Four levels (from portals.example.yml)
 &lt;a class="anchor" href="#four-levels-from-portalsexampleyml">#&lt;/a>
&lt;/h2>
&lt;pre tabindex="0">&lt;code>Level 0. local_parser → custom script per company
Level 1. Playwright → browser scrape of careers_url
Level 2. HTTP JSON → public ATS/board APIs (providers)
Level 3. WebSearch → site: filtered search queries
&lt;/code>&lt;/pre>&lt;p>&lt;strong>Default &lt;code>raven discover&lt;/code>&lt;/strong> uses HTTP JSON at scale (ATS reverse scan + board feeds) — not levels 0–1 per company, and &lt;strong>not level 3&lt;/strong>.&lt;/p></description></item><item><title>Filters</title><link>https://raven.nopejs.me/docs/job-discovery/filters/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://raven.nopejs.me/docs/job-discovery/filters/</guid><description>&lt;h1 id="discovery-filters">
 Discovery filters
 &lt;a class="anchor" href="#discovery-filters">#&lt;/a>
&lt;/h1>
&lt;p>Filters apply during &lt;code>raven discover&lt;/code>, &lt;code>raven scan-ats&lt;/code>, &lt;code>raven scan-boards&lt;/code>, and &lt;code>raven query&lt;/code>.&lt;/p>
&lt;h2 id="cli-flags">
 CLI flags
 &lt;a class="anchor" href="#cli-flags">#&lt;/a>
&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Flag&lt;/th>
 &lt;th>Description&lt;/th>
 &lt;th>Example&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;code>--q &amp;quot;keywords&amp;quot;&lt;/code>&lt;/td>
 &lt;td>Title must match (comma-separated)&lt;/td>
 &lt;td>&lt;code>--q &amp;quot;backend, engineer&amp;quot;&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--not &amp;quot;words&amp;quot;&lt;/code>&lt;/td>
 &lt;td>Title must not contain&lt;/td>
 &lt;td>&lt;code>--not &amp;quot;nurse, sales&amp;quot;&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--loc Remote,EU&lt;/code>&lt;/td>
 &lt;td>Location allow-list&lt;/td>
 &lt;td>&lt;code>--loc Remote,India&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--noloc &amp;quot;On-site&amp;quot;&lt;/code>&lt;/td>
 &lt;td>Location block-list&lt;/td>
 &lt;td>&lt;code>--noloc &amp;quot;San Francisco&amp;quot;&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--since N&lt;/code>&lt;/td>
 &lt;td>Posted within last N days&lt;/td>
 &lt;td>&lt;code>--since 7&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--ats greenhouse,lever&lt;/code>&lt;/td>
 &lt;td>Limit ATS platforms&lt;/td>
 &lt;td>&lt;code>--ats ashby,workday&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--max N&lt;/code>&lt;/td>
 &lt;td>Cap total results&lt;/td>
 &lt;td>&lt;code>--max 100&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>--limit N&lt;/code>&lt;/td>
 &lt;td>Per-provider limit&lt;/td>
 &lt;td>&lt;code>--limit 50&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="config-vs-cli">
 Config vs CLI
 &lt;a class="anchor" href="#config-vs-cli">#&lt;/a>
&lt;/h2>
&lt;p>When CLI flags are omitted, Raven merges filters from &lt;code>config/portals.yml&lt;/code>:&lt;/p></description></item><item><title>openjobdata</title><link>https://raven.nopejs.me/docs/job-discovery/openjobdata/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://raven.nopejs.me/docs/job-discovery/openjobdata/</guid><description>&lt;h1 id="openjobdata-index">
 openjobdata index
 &lt;a class="anchor" href="#openjobdata-index">#&lt;/a>
&lt;/h1>
&lt;p>Raven syncs the &lt;a href="https://openjobdata.com/documentation">openjobdata&lt;/a> dataset into a local SQLite database for fast offline search.&lt;/p>
&lt;h2 id="sync">
 Sync
 &lt;a class="anchor" href="#sync">#&lt;/a>
&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>raven sync-jobs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>raven sync-jobs --days &lt;span style="color:#ae81ff">3&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="what-happens">
 What happens
 &lt;a class="anchor" href="#what-happens">#&lt;/a>
&lt;/h3>
&lt;ol>
&lt;li>Downloads companies registry from HuggingFace bucket &lt;code>Invicto69/Jobs-Dataset-bucket&lt;/code>&lt;/li>
&lt;li>Fetches recent daily parquet deltas&lt;/li>
&lt;li>Upserts into &lt;code>data/jobs.db&lt;/code>&lt;/li>
&lt;li>Exports ATS company slug lists to &lt;code>data/cache/ats-companies/&lt;/code>&lt;/li>
&lt;/ol>
&lt;h3 id="authentication">
 Authentication
 &lt;a class="anchor" href="#authentication">#&lt;/a>
&lt;/h3>
&lt;p>If sync returns HTTP 401:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># .env&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>HF_TOKEN&lt;span style="color:#f92672">=&lt;/span>hf_xxxxxxxx
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Create a read token at &lt;a href="https://huggingface.co/settings/tokens">huggingface.co/settings/tokens&lt;/a>.&lt;/p>
&lt;h2 id="query-local-index">
 Query local index
 &lt;a class="anchor" href="#query-local-index">#&lt;/a>
&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>raven query --q &lt;span style="color:#e6db74">&amp;#34;software engineer&amp;#34;&lt;/span> --since &lt;span style="color:#ae81ff">7&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>raven query --q &lt;span style="color:#e6db74">&amp;#34;ML engineer&amp;#34;&lt;/span> --ats greenhouse,lever --json
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Same filter flags as discover: &lt;code>--q&lt;/code>, &lt;code>--not&lt;/code>, &lt;code>--loc&lt;/code>, &lt;code>--since&lt;/code>, &lt;code>--ats&lt;/code>, &lt;code>--max&lt;/code>.&lt;/p></description></item></channel></rss>