Turn your LinkedIn data export into an interactive, privacy-first insights dashboard - entirely in your browser.
LinkedIn lets you download your full data export but offers no first-class way to actually understand it. This app reads the export ZIP entirely in your browser, builds dashboards, computes deterministic findings, and - optionally - enriches them with an LLM you control via your own API key. Nothing is uploaded, nothing is logged, no server is involved.
Your data never leaves your device. The only network calls happen if you choose to run the optional AI step, in which case the request goes directly from your browser to the LLM provider you selected, using your API key. The author of this site never sees your data or your key.
- Drag-and-drop ZIP parsing -
jszip+papaparsedecode your export entirely client-side. - Eight Direct Insights dashboards - Overview, Network, Content, Jobs, Career, Messaging, Ads & Inferences, and Account & Security, with charts (Recharts) and curated KPIs.
- Three AI Insights views - Profile Optimizer, Job Search Strategy, and 30-day Action Plan, each rendered from a single structured LLM response.
- Deterministic findings engine - evidence-backed insights computed locally with no LLM required.
- Composite scores - visibility, network health, career momentum, content output, and privacy posture (0–100).
- Sample data mode - one-click download of a synthetic LinkedIn export ZIP so you can try the app without your own data.
- BYO-key AI - OpenRouter, OpenAI, Anthropic, Google Gemini, or HuggingFace. Quick-pick chips for popular models, free-text input for any model id, and a "Browse all models" deep-link per provider.
- On-device inference (WebLLM) - run open-source models (Llama, Mistral, Qwen, Gemma, Phi, …) entirely in your browser via WebGPU. No API key, no network call - weights cached locally after first load.
- LLM call log - per-call table with date, provider, routed model, tokens (input/output), cost, speed (tok/s), and finish reason - similar to OpenRouter's activity view.
- Payload preview - inspect the exact aggregate JSON sent to the LLM before clicking Generate.
- Downloadable HTML report - single self-contained
.htmlwith aggregate metrics, SVG charts, findings, and the AI narrative. Raw rows, message bodies, IPs, and contact identifiers are intentionally excluded. - Static-host friendly - zero backend; ships to GitHub Pages, Cloudflare Pages, Vercel, or any static host.
A live build of main is auto-deployed to GitHub Pages: https://bcastelino.github.io/linkedin-data-visualizer/
- Node.js 20+ (LTS 22 recommended)
- npm 10+
git clone https://github.com/bcastelino/linkedin-data-visualizer.git
cd linkedin-data-visualizer
npm install
npm run devOpen http://localhost:5173 and drop your LinkedIn ZIP onto the upload zone.
| Command | Description |
|---|---|
npm run dev |
Start the Vite dev server with HMR |
npm run build |
Type-check and produce a production build in dist/ |
npm run preview |
Serve the production build locally |
npm run lint |
Type-check the project (no emit) |
- Sign in to LinkedIn → Settings & Privacy → Data Privacy → Get a copy of your data.
- Choose "Want something in particular?" for the fastest export.
- Wait for the email (usually < 10 minutes for the fast option, up to 24 h for the larger archive).
- Download the ZIP - do not unzip it. Drop it directly onto this app.
Full guide: LinkedIn Help - Downloading Your Account Data.
LinkedIn Settings: Download my Data.
| Layer | Behavior |
|---|---|
| ZIP parsing | 100% client-side. The file never touches a server. |
| Message bodies | Reduced to { length, hasUrl, hasAttachment, monthBucket } immediately after parsing. Plain-text content is dropped before any further processing. |
| AI payload | Only an aggregated metrics object is sent. You can preview the exact JSON with the "Preview payload" button before clicking Generate. |
| AI request routing | Browser → provider's official API directly. The author of this site is never on the path. |
| API keys | Stored only in localStorage if you tick "Remember on this device". You can clear them anytime. |
| HTML report | Excludes raw rows, message bodies, IPs, emails, phone numbers, security challenges, and verification details. |
What's never sent: connection names, message content, recipients, profile URLs, raw timestamps, login IPs, or any row-level data.
Bring your own key - pick whichever you prefer:
| Provider | Highlight | Get a key |
|---|---|---|
| OpenRouter (default) | Unified gateway, openrouter/free smart router, 100+ models |
openrouter.ai/keys |
| OpenAI | GPT-4o, GPT-4 Turbo | platform.openai.com/api-keys |
| Anthropic | Claude 3.5 Sonnet, Opus | console.anthropic.com |
| Google Gemini | 1.5 Pro / Flash, free tier available | ai.google.dev |
| HuggingFace | Open-source models (Llama, Mistral, Qwen, Gemma, …) | huggingface.co/settings/tokens |
| Local (WebLLM) | Runs entirely in your browser via WebGPU - no API key, no network | mlc.ai/models |
The model field accepts any model id from the provider - quick-pick chips are provided for convenience, and a "Browse all models" link opens each provider's catalog.
Select the Local (WebLLM) provider to run a model fully in-browser via @mlc-ai/web-llm. The first run downloads the model weights into your browser's Cache Storage / IndexedDB (typically 1–4 GB depending on the model); subsequent runs are instant. Requires a WebGPU-capable browser (latest Chrome, Edge, or Brave on a desktop with a discrete or integrated GPU).
src/
├── components/ UI: dashboards, panels, AI tab, upload zone, charts
│ ├── ai/ AI insight tabs: Profile Optimizer, Job Search Strategy, 30-day Action Plan
│ └── tabs/ Direct-insight dashboards (overview, network, content, jobs, career, …)
├── lib/
│ ├── zip.ts ZIP extraction helpers
│ ├── csv.ts CSV parsing helpers (papaparse wrappers)
│ ├── parse.ts ZIP → typed `ParsedExport`
│ ├── tabFiles.ts Per-tab file-usage manifest (powers the "Files used" popover)
│ ├── insights.ts Deterministic metrics & scoring
│ ├── llm.ts Provider adapters + payload builder + JSON schema
│ ├── webllm.ts In-browser WebGPU engine wrapper (@mlc-ai/web-llm)
│ ├── sampleData.ts Synthetic LinkedIn export generator
│ └── report.ts Self-contained HTML report generator
├── store.ts Zustand store (state, LLM keys, WebLLM status, call log)
└── types.ts Shared TypeScript types
- Upload -
UploadZonehands theFiletoparse.ts, which streams CSVs out of the ZIP (zip.ts+csv.ts) and emits a typedParsedExport. - Insights -
insights.tsrolls the parsed data intoDerivedInsights(totals, monthly trends, top-N lists, scores). - AI (optional) -
llm.ts#buildPromptPayloadextracts an aggregate-only payload and sends it to the chosen provider through one of thecallOpenRouter/callOpenAI/callAnthropic/callGoogle/callHuggingFace/callWebLLMadapters. Each adapter normalizes token usage, finish reason, model used, and cost into a commonLLMCallMetaconsumed by the call-log table. - Report -
report.tsproduces a stand-alone HTML document with inline SVG charts and the AI narrative.
A ready-to-use workflow ships at .github/workflows/deploy.yml.
- Push this repo to GitHub (any name; the workflow reads the repo name dynamically).
- Settings → Pages → Source → GitHub Actions.
- Push to
main. The workflow builds withVITE_BASE=/<repo-name>/and publishes to thegithub-pagesenvironment.
For a different host (Cloudflare Pages, Vercel, Netlify), just run:
VITE_BASE="/" npm run build…and upload the dist/ folder.
| Area | Choice |
|---|---|
| Framework | React 18 + TypeScript |
| Build tool | Vite 5 |
| Styling | Tailwind CSS 3 |
| State | Zustand |
| Charts | Recharts |
| Parsing | JSZip + Papaparse |
| On-device LLM | @mlc-ai/web-llm (WebGPU) |
| Icons | Lucide |
- WebLLM adapter for fully on-device inference (WebGPU)
- Synthetic sample-data mode for try-before-export
- Dedicated Jobs dashboard and AI Insights tabs (Profile Optimizer, Job Search Strategy, 30-day Action Plan)
- Local Ollama / LM Studio adapter (custom OpenAI-compatible base URL)
- Per-provider price table to populate Cost in the call log for non-OpenRouter providers
- PDF export (in addition to HTML report)
- Year-over-year comparison views
- i18n
Have an idea? Open an issue.
Contributions are welcome. The general flow:
- Fork the repo and create a branch (
git checkout -b feat/your-feature). - Make your change with tests / type-checks passing (
npm run lint). - Open a PR with a clear description and screenshots if it touches UI.
Please keep the privacy guarantees intact - any change that would send raw rows, message bodies, or contact identifiers off-device must be rejected or made strictly opt-in with an explicit confirmation.
- LinkedIn for providing a complete data export.
- The maintainers of JSZip, Papaparse, Recharts, Zustand, and Lucide.
- OpenRouter for making provider-agnostic LLM access trivial.
Released under the MIT License.