{% extends "base.html" %} {% block title %}Companies — Job Cannon{% endblock %} {% block content %}

Companies

Tracked companies with ATS discovery and careers page scraping.

{# Scan ATS button. The POST returns a polling-progress fragment that lives in #scan-result and re-fetches /companies/scan/status every 2s. hx-disabled-elt only blocks the button for the duration of the POST itself (~ms); polling keeps the user informed without blocking. #}
{# Scan result slot. The Scan ATS button replaces this div with either the progress fragment (which polls every 2s) or the terminal done/error fragment. Both fragments keep id="scan-result" so subsequent polls swap into the same slot. If a scan is already running when the page loads (e.g. user clicked Scan ATS, navigated away, came back), inline the polling progress fragment so they immediately see "Scanned X of N" instead of an empty card. #} {% if running_scan %} {% with session_id=running_scan.session_id, total=running_scan.total, scanned=running_scan.scanned %} {% include "companies/_scan_ats_progress.html" %} {% endwith %} {% else %}
{% endif %} {# Read-only stat cards, so an SSE-driven innerHTML swap is non-disruptive #} {# (nothing here holds focus/scroll). The companies TABLE below is #} {# deliberately NOT wired to SSE: it has search + infinite-scroll #} {# pagination, and an auto-refetch would reset the user's scroll position. #}
{% include "companies/_health_metrics.html" %}
{# Suggested companies (WP6) — feed-frequent, untracked. Omitted entirely when empty. Each Track button swaps itself to the ✓ state in place. #} {% if suggested_companies %}

Companies in your feed

These show up often in your ingested jobs but aren't tracked yet. Track one and Job Cannon will try to find its job board (Greenhouse / Lever / Ashby / Workday / SmartRecruiters) and scan it on every sync.

{% endif %}
{{ total_count }} companies
{% include "companies/_table.html" %}
{% endblock %}