An open-source Chrome extension that helps job seekers check whether employers shown on LinkedIn and SEEK New Zealand are accredited by Immigration New Zealand (INZ), without leaving the page.
The project deliberately separates official accreditation evidence from the evidence that maps a company page to a legal employer. A result can show:
- official INZ employer data: legal name, trading name, NZBN, and accreditation expiry, plus the time the Inspector accepted that observation;
- a user-confirmed LinkedIn or SEEK association;
- a derived exact official/trading-name match, which is not a community confirmation; or
- a recent no-published-match observation, which is not proof that an employer is unaccredited.
No live lookup runs when a page loads. A check starts only after the user selects Check NZ accreditation, and that action makes at most one live INZ request.
- Product site: nzaei.zemo.bio
- Chrome Web Store: Install the extension
- Extension API:
https://nzaei.zemo.bio/api - Public read-only API:
https://nzaei.zemo.bio/api/public/v1 - Public API guide: nzaei.zemo.bio/public-api
- Open-data catalog: data.nzaei.zemo.bio/catalog.json
The extension currently supports:
- LinkedIn company profiles, direct job pages, and job-search detail panes;
- SEEK NZ company profiles, job pages, search-result detail panes, and homepage recommendation detail panes.
Use the toolbar popup to pause or resume the Inspector. When paused, it does not mount new page widgets or run checks; refreshing a page after re-enabling it restores the widget.
| Path | Purpose |
|---|---|
extension/ |
WXT Manifest V3 Chrome extension (currently 1.0.0). |
api/ |
Cloudflare Worker, D1 schema/importer, Worker API, and scheduled R2 open-data publication (currently service 0.8.0). |
landing/ |
Astro product site, public API description, privacy policy, changelog, insights, and open-data pages. |
scripts/employer-refresh/ |
Operator-run sequential refresh for employers nearing expiry; it calls INZ and D1 directly, outside the public API. |
data/original-data/ |
Source MBIE OIA workbooks used for official imports. |
docs/ |
Architecture/API contract and Cloudflare deployment notes. |
LinkedIn / SEEK page
│ explicit user action
▼
Chrome extension ─────► Cloudflare Worker + D1
│ │
│ ├─ canonical employer records
│ ├─ community page associations
│ └─ short-lived no-match / refresh controls
│
└────► INZ lookup endpoint (only when the Worker requires it)
Cloudflare scheduled handler ─────► R2 dated open-data snapshots
Operator refresh script ──────────► INZ + production D1
Public integrations ──────────────► read-only Worker routes + D1
The Worker validates and stores browser-submitted INZ payloads but never calls INZ itself. The separate operator refresh script is intentionally outside the extension request path. Public integrations can only read employer records by NZBN or bounded name search; they cannot access platform identities, community associations, refresh controls, or any write route.
Each deployable project has its own dependency tree and scripts. Use Node.js 22 or later.
# Extension
cd extension
npm install
npm run check
# Worker API (typegen, TypeScript, and tests)
cd ../api
npm install
npm run check
# Landing site
cd ../landing
npm install
npm run buildFor local extension work, run npm run dev from extension/ and load extension/.output/chrome-mv3 if WXT does not open Chrome automatically. The API and import workflow are documented in api/README.md; deployment order is in docs/cloudflare-deployment.md.
employers is the canonical NZBN-keyed dataset. It is populated by validated official MBIE imports and user-triggered INZ observations. Platform associations are community data, not INZ facts; a unique exact name match is derived on demand and never persisted as a confirmation.
The Worker publishes a fixed, privacy-safe projection of the canonical dataset as immutable dated CSV snapshots to R2. It also lists an original MBIE OIA workbook for download. These files use NOASSERTION licence status and are dated observations, not a live official register. Use those snapshots for bulk integrations; the public API is deliberately limited to individual lookup and bounded search.
For the complete extension contract, data model, freshness rules, API error semantics, and provenance model, read docs/extension-api-ssot.md. For machine-readable references, see the extension OpenAPI 3.1 document, public API OpenAPI 3.1 document, public API guide, and open-data guide.
The extension does not use a LinkedIn or SEEK account identity. It keeps a random installation UUID in extension storage; the API hashes it before storing a confirmation. It is a rate-limit and selection key, not authentication.
This independent project is not an INZ product and does not provide immigration or legal advice. Verify important decisions with INZ or the employer. See the full privacy policy and how results work.