---
name: career-opportunity-analysis
category: research
description: Analyze external job boards and company career pages to find opportunity matches for a user's developer profile.
created: 2026-06-16
---

# Career Opportunity Analysis

Analyze external job boards, company career pages, and opportunity listings to find matches for a user's profile.

## Trigger
User asks to find jobs, gigs, contracts, or opportunities that fit them on a specific website or platform.

## Workflow

### 1. Load User Profile from Memory
- Read the user's stored profile from `memory` (target=user) before searching.
- Verify: current role/seniority, location constraints, tech stack, availability timeline.
- Pitfall: Do NOT assume "Full Stack" implies senior-level. Confirm actual years of experience and education background.

### 2. Navigate and Survey the Site
- Use `browser_navigate` to load the target site.
- Accept/dismiss cookie dialogs if they block content.
- Check for a dedicated "/jobs", "/careers", "/vacatures", or "/vacancies" path.

### 3. Extract Listing Data
Strategy A — Static Snapshot:
- Use `browser_snapshot` (full=true) to read the page.
- Scroll with `browser_scroll` if content is paginated.

Strategy B — Dynamic DOM Extraction (when snapshots truncate or scroll doesn't reveal content):
- Use `browser_console` with a JavaScript IIFE to query the live DOM:
```javascript
(()=>{
  const jobs=[];
  document.querySelectorAll('a').forEach(a=>{
    const txt=a.textContent.toLowerCase();
    if(txt.includes('<KEYWORD>')){
      jobs.push({
        text: a.textContent.trim(),
        href: a.getAttribute('href')
      });
    }
  });
  return jobs;
})()
```
- Iterate keywords if needed (company names, role titles).
- Once job links are harvested, navigate to each with `browser_navigate`.

Strategy C — Filter Widgets:
- If the site has search/filter widgets, interact with them via `browser_type`/`browser_click` to narrow results before extraction.

### 4. Deep-Dive Specific Listings
- Navigate to individual job detail pages.
- Use `browser_snapshot` (full=true) to capture the description, requirements, tech stack, location, remote policy, and contact info.
- **Visit the company's own website** (not just the job board listing). Navigate to their homepage to understand their product/service, then check for a `/careers` or `/jobs` page on their own domain — they may have more detail or a different application method.
- If the job listing has a "Solliciteer nu" / "Apply now" button, click it to see where it leads (mailto link, external form, LinkedIn, or company ATS). Don't assume it's a form — it may be a `mailto:` in disguise.

### 5. Assess Fit
For each listing, evaluate against the user's profile:
- Tech stack overlap (primary and secondary languages/frameworks).
- Experience level match (Junior / Medior / Senior).
- Location / remote compatibility.
- Domain interest alignment.
- Highlight AI/data roles separately if the user expresses interest.

### 6. Present Findings
- Shortlist: all discovered listings (company, title, date posted).
- Fitting subset: listings that match the user's confirmed profile.
- Deep-dive expansion: one listing at a time if the user asks "expand on N".

### 7. Deep-Dive a Single Listing (when user says "I want to work there")
- Follow the detailed workflow in `references/single-listing-deep-dive.md`.
- Extract full contact info, company website, and exact application method.
- Provide a tech-stack comparison with syntax examples for unfamiliar tools.
- Offer to draft an application email if the method is email-based.

### 8. Update Memory
- Save any new profile details revealed during the session (updated stack, seniority, portfolio URLs, etc.) to `memory` target=user.

## Techniques

### Harvesting Paginated Job Cards
When a page uses infinite scroll or lazy-loaded lists, the DOM often contains more data than the accessibility snapshot reveals. Inject JavaScript via `browser_console` to read `document.querySelectorAll(...)` across the full DOM tree.

Example for Corda Campus-style cards:
```javascript
(()=>{
  const cards = document.querySelectorAll('div[class*="vacature"], div[class*="job"], article, .card');
  return Array.from(cards).map(c => c.textContent.replace(/\s+/g,' ').trim());
})()
```

### Mapping Text to Links
When card text is available but the `href` is hidden in nested elements, extract pairs:
```javascript
(()=>{
  const jobs=[];
  document.querySelectorAll('a').forEach(a=>{
    const txt=a.textContent.toLowerCase();
    if(txt.includes('<TARGET>')){
      jobs.push({text: a.textContent.trim(), href: a.getAttribute('href')});
    }
  });
  return jobs;
})()
```

## Pitfalls

1. **Assuming seniority from stack**: A user listing PHP/Laravel/Angular/TypeScript/Docker may be junior. Always confirm years of experience or educational background before labeling a role "under-leveled" or "over-leveled".
2. **Truncated snapshots**: `browser_snapshot` truncates after ~8000 chars. Use `browser_console` DOM queries for dense listing pages.
3. **Cookie walls blocking content**: Always handle cookie consent dialogs first; otherwise listings may not load.
4. **Stale listings**: Check the posted date. If a listing is older than ~90 days, flag it as potentially expired.
