Jobsy is a Chrome extension (Manifest V3) that helps you work through Wellfound job listings with AI: understand the role, check fit against your resume, draft application answers, and ask questions about the posting. It runs only on wellfound.com and opens as an in-page sidebar next to the job content.
When a specific job post is detected, the header shows the role title and company (scraped from the page, including job drawer and job detail layouts). If you are on Wellfound but not on a single listing (for example /jobs or a company page without a focused job), the header shows a red error state explaining that you need to open an actual job post.
| Tab | Purpose |
|---|---|
| Insight | Plain-language summary of the role: expectations, stack, and what the employer is looking for. |
| Apply | Reads fields from the open apply form (modal or slide-in drawer), drafts answers from your bundled resume via the AI, then lets you Fill form to write answers into the page (text inputs, textareas, selects, and Yes/No-style radios). |
| Match | Structured fit analysis: score and sections grounded in the job description and your resume. |
| Ask | Chat-style Q&A about the job and your background (not a substitute for submitting the employer’s form). |
- On URLs like
wellfound.com/jobs?job_listing_slug=…, the extension does not click “Apply” to open another layer—the apply UI is assumed to already be in the drawer. - Choice questions (e.g. Yes/No) are sent to the model with clear options; the UI shows question text only, without synthetic “choose one” suffixes in the draft list.
- While answers are generating, the panel shows a loading state instead of streaming raw JSON; when the response is ready, answers appear in a readable list.
A small Jobsy FAB on Wellfound toggles the sidebar. The extension can inset the page so content is not hidden behind the panel (with responsive behavior on narrow viewports).
- Alt+Shift+M (Mac and Windows/Linux): toggle the Jobsy sidebar (
chrome.commandsin the manifest).
Clicking the extension icon opens a settings-style popup: API key status (from build), Test connection to OpenRouter, and the toggle shortcut reminder.
src/extension/
├── manifest.json # MV3: content script on wellfound.com only
├── background.ts # Forwards messages to the active tab (job data, apply extract/fill)
├── content-entry.tsx # Injects sidebar host + FAB, bridges page ↔ extension UI
├── popup.tsx / popup.html # Toolbar popup (API check)
├── panel/ # React UI: tabs, job bar, copilots
├── lib/
│ ├── extractor.ts # Job + apply-form field detection, fill helpers
│ ├── prompts.ts # System/user prompts for each copilot
│ ├── openrouter.ts # Chat Completions API, streaming, retries
│ ├── storage.ts # Build-time API key
│ ├── resume.ts # Resume text from bundled MDX
│ └── …
├── data/resume.mdx # Your resume source for AI prompts (edit and rebuild)
└── sidepanel.css # Tailwind entry → content.css for injected UI
- Build uses esbuild for
background,content, andpopupbundles; Tailwind CLI compilessidepanel.css→content.css. - The panel is the same React tree used inside a Shadow DOM host on the page so styles stay isolated from Wellfound’s CSS.
- API: OpenRouter (
/api/v1/chat/completions). - Default model:
anthropic/claude-sonnet-4(seesrc/extension/lib/openrouter.ts). - Calls are made from the extension context (panel / background flow) using your API key.
-
Create a
.envfile at the repository root (not committed):OPENROUTER_API_KEY=sk-or-...
-
Run
npm run build:extension. The build script reads.envand inlines the key into the bundle as__JOBSY_API_KEY__(seescripts/build-extension.mjsandsrc/extension/lib/storage.ts). -
If the key is missing, the build prints a warning and copilots that need the API will fail until you rebuild with a key.
Security note: The key is embedded in shipped extension files anyone with the unpacked folder can read. For a public distribution you would want a different auth model (e.g. user sign-in and server-side proxy). For personal or team builds, keep the unpacked build private.
Edit src/extension/data/resume.mdx. It is imported as raw text and passed into prompts. Rebuild the extension after changes.
- Node.js (LTS recommended)
- npm
- Chrome (or Chromium) for loading the unpacked extension
Use this when you want to run the extension on your machine.
-
Install dependencies
npm install
-
Create
.envin the repo rootMinimum for extension features:
OPENROUTER_API_KEY=sk-or-...
Also needed if you run the Next.js app locally:
DATABASE_URL=postgres://USER:PASSWORD@HOST:5432/DB_NAME UPLOADTHING_TOKEN=YOUR_UPLOADTHING_TOKEN # Optional (defaults to http://localhost:3000) OPENROUTER_HTTP_REFERER=http://localhost:3000 -
Build the extension
npm run build:extension
-
Load it in Chrome
- Open
chrome://extensions - Enable Developer mode
- Click Load unpacked
- Select
dist/extension
- Open
-
Use it on Wellfound
- Open any
wellfound.comjob listing page - Toggle the sidebar with Alt+Shift+M
- Open any
-
After code changes
npm run build:extension
Then click Reload on the extension card in
chrome://extensions, and refresh your Wellfound tab.
Optional: run the web app:
npm run dev| Command | Description |
|---|---|
npm install |
Install dependencies |
npm run build:extension |
Build the Chrome extension to dist/extension/ |
npm run dev |
Run the Next.js app (optional; separate from the extension) |
npm run build |
Production build of the Next.js app |
npm run build:all |
Next.js build + extension build |
npm run lint |
ESLint |
-
Build
npm install npm run build:extension
-
Load in Chrome
- Open
chrome://extensions - Enable Developer mode
- Load unpacked → select the
dist/extensiondirectory inside this repo (e.g.…/jobsy/dist/extension)
- Open
-
After code changes
npm run build:extension
Then hit Reload on the extension card in
chrome://extensions, and refresh any open Wellfound tabs.
Output layout (typical):
dist/extension/manifest.jsondist/extension/content.js/content.cssdist/extension/background.jsdist/extension/popup.js/popup.html/popup.cssdist/extension/icons/
Defined in manifest.json:
storage– reserved for extension preferences where usedtabs,activeTab– resolve the active tab when the panel asks the background script to message the content scripthost_permissions:https://wellfound.com/*– content script and page access only on Wellfound
The extension does not request all-sites access by default.
- Wellfound-only: UI and scripts run on
wellfound.commatches only. - Job detection follows rules in
extractor.ts(isWellfoundJobPage, listing slugs, job URLs). If the site changes structure, extraction may need updates. - Apply autofill depends on the same field ordering as extraction; complex widgets (e.g. some React Select flows) may not fill automatically.
- Disabled or gated fields (e.g. until profile/location is fixed) may still block submission even when values are inserted.
- TypeScript, React 19
- esbuild (extension bundles)
- Tailwind CSS v4 (panel styles compiled into
content.css) - marked (markdown rendering in the panel)
- Next.js (present in the repo for optional web usage; the primary product described here is the extension)
jobsy/
├── README.md # This file
├── package.json
├── scripts/build-extension.mjs
├── src/
│ ├── extension/ # Chrome extension source
│ └── app/ # Next.js app (optional)
└── dist/extension/ # Generated extension (after build; gitignored)
- Prefer small, focused changes when adjusting extraction or prompts; the DOM varies between job drawer and full job pages.
- After editing
resume.mdx,openrouter.ts(model), or prompts, runnpm run build:extensionand reload the extension. - Use the toolbar popup Test connection to verify OpenRouter credentials after a new build.
Jobsy — version and branding as in manifest.json (0.1.0). Add a LICENSE file if you publish the project publicly.